home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Tool Chest / Dev.CD Feb 97 TC.toast / Sample Code / Development Tools & Languages / AppsToGo / DTS.Lib / Window2.c < prev   
Encoding:
C/C++ Source or Header  |  1994-09-22  |  97.4 KB  |  3,851 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:     DTS.Lib
  5. ** File:        window2.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1993 Apple Computer, Inc.
  9. ** All rights reserved.
  10. */
  11.  
  12. /* You may incorporate this sample code into your applications without
  13. ** restriction, though the sample code has been provided "AS IS" and the
  14. ** responsibility for its operation is 100% yours.  However, what you are
  15. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  16. ** after having made changes. If you're going to re-distribute the source,
  17. ** we require that you make it clear in the source that the code was
  18. ** descended from Apple Sample Code, but that you've made changes. */
  19.  
  20.  
  21.  
  22. /*****************************************************************************/
  23.  
  24.  
  25.  
  26. #include "DTS.Lib2.h"
  27. #include "DTS.Lib.protos.h"
  28.  
  29. #ifndef __BALLOONS__
  30. #include <Balloons.h>
  31. #endif
  32.  
  33. #ifndef __DESK__
  34. #include <Desk.h>
  35. #endif
  36.  
  37. #ifndef __ERRORS__
  38. #include <Errors.h>
  39. #endif
  40.  
  41. #ifndef __FONTS__
  42. #include <Fonts.h>
  43. #endif
  44.  
  45. #ifndef __CLPROCS__
  46. #include "ListControlProcs.h"
  47. #endif
  48.  
  49. #ifndef __LOWMEM__
  50. #include <LowMem.h>
  51. #endif
  52.  
  53. #ifndef __MOVIES__
  54. #include <Movies.h>
  55. #endif
  56.  
  57. #ifndef __RESOURCES__
  58. #include <Resources.h>
  59. #endif
  60.  
  61. #ifndef __SCRIPT__
  62. #include <Script.h>
  63. #endif
  64.  
  65. #ifndef __TOOLUTILS__
  66. #include <ToolUtils.h>
  67. #endif
  68.  
  69. #ifndef __UTILITIES__
  70. #include "Utilities.h"
  71. #endif
  72.  
  73.  
  74.  
  75. /*****************************************************************************/
  76.  
  77.  
  78.  
  79. #ifdef powerc
  80. #pragma options align=mac68k
  81. #endif
  82. typedef struct {
  83.     Rect            contrlRect;
  84.     short            contrlValue;
  85.     unsigned char    contrlVis;
  86.     short            contrlMax;
  87.     short            contrlMin;
  88.     short            procID;
  89.     long            contrlRfCon;
  90.     Str255            contrlTitle;
  91. } CtlTemplate;
  92. #ifdef powerc
  93. #pragma options align=reset
  94. #endif
  95.  
  96. extern short    gTECtl;
  97. extern short    gListCtl;
  98. extern short    gCIconCtl;
  99. extern short    gPICTCtl;
  100. extern short    gDataCtl;
  101.  
  102. extern Handle    gPopupProc;
  103.  
  104. extern short            gPrintPage;                    /* Non-zero means we are printing. */
  105. extern short            gMinVersion, gMaxVersion;
  106. extern Boolean            gInBackground;
  107. extern WindowTemplate    gWindowTemplate, gOpenedWindowTemplate;
  108.  
  109. extern short            gTypeListLen;
  110. extern SFTypeList        gTypeList;
  111. extern long                gAppWindowAttr;
  112. extern OSType            gAppWindowType;
  113. extern Boolean            gNoDefaultDocument;
  114. extern OSErr            gGetWindowErr;
  115.  
  116. OSType                    *gTypeListPtr = gTypeList;
  117. short                    gBeginUpdateNested;
  118. TreeObjHndl                gWindowFormats;
  119. OSErr                    gDialogErr;
  120. HideWindowProcPtr        gHideWindowProc;
  121. GetPreferenceProcPtr    gGetPreferenceProc;
  122.  
  123. static RgnHandle        gKeepUpdateRgn;
  124. static WindowPtr        gOldPort;
  125.  
  126. RgnHandle    gCursorRgn;
  127.     /* The current cursor region.  The initial cursor region is an empty
  128.     ** region, which will cause WaitNextEvent to generate a mouse-moved
  129.     ** event, which will cause us to set the cursor for the first time. */
  130.  
  131. static Cursor    gCursor;
  132. CursPtr            gCursorPtr;
  133.     /* The current cursor that applies to gCursorRgn.  These values
  134.     ** are here to shorten the re-processing time for determining the
  135.     ** correct cursor after an event.  This is specifically so that characters
  136.     ** can be typed into the TextEdit control faster.  If we spend a great
  137.     ** deal of time per-event recalculating the cursor region, text entry for
  138.     ** the TextEdit control slows down considerably.  If you want to override
  139.     ** the time savings because you are changing the cursor directly, either
  140.     ** set gCursorPtr to nil, or call DoSetCursor to set the cursor.
  141.     ** DoSetCursor simply sets gCursorPtr to nil, as well as setting
  142.     ** the cursor. */
  143.  
  144. static Rect                    OldLocWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo);
  145. static PositionWndProcPtr    gOldLocProc;
  146.  
  147. static pascal void    DefaultScrollAction(ControlHandle scrollCtl, short part);
  148. static Boolean        DefaultScroll(ControlHandle ctl, short part, EventRecord *event);
  149.  
  150.  
  151.  
  152. /*****************************************************************************/
  153. /*****************************************************************************/
  154.  
  155. #ifdef applec
  156. #pragma segment ATGWindow
  157. #endif
  158.  
  159. /*****************************************************************************/
  160. /*****************************************************************************/
  161.  
  162.  
  163.  
  164. /* This function creates a new application window.  An application window
  165. ** contains a document which is referenced by a handle in the refCon field. */
  166.  
  167. OSErr    DoNewWindow(FileRecHndl frHndl, WindowPtr *retWindow, WindowPtr relatedWindow, WindowPtr behind)
  168. {
  169.     WindowPtr            oldPort, window;
  170.     FileRecHndl            ffrHndl;
  171.     ControlHandle        ctl;
  172.     Rect                ctlRect, contRect, userState, sizeInfo, rct, rct2, msrct, oldPlaceRct;
  173.     short                h, v, hDocSize, vDocSize;
  174.     long                wkind, wwkind, attributes;
  175.     OSErr                err;
  176.     PositionWndProcPtr    proc;
  177.     GDHandle            device;
  178.     PixMapHandle        pmap;
  179.     TreeObjHndl            pref;
  180.  
  181.     gCursorPtr = nil;        /* Force recalc of cursor. */
  182.  
  183.     if (!frHndl) return(noErr);
  184.     attributes = (*frHndl)->fileState.attributes;
  185.  
  186.     err = noErr;
  187.     GetPort(&oldPort);
  188.  
  189.     proc = (*frHndl)->fileState.getDocWindow;
  190.  
  191.     if (attributes & kwStaggerWindow) proc = StaggerWindow;
  192.     if (attributes & kwCenterWindow)  proc = CenterWindow;
  193.  
  194.     gOldLocProc = proc;
  195.     if (attributes & kwOpenAtOldLoc) {
  196.         proc = OldLocWindow;    /* Try to open window at old location. */
  197.         if (attributes & kwRuntimeOnlyDoc) {
  198.             if (gGetPreferenceProc) {
  199.                 pref = (*gGetPreferenceProc)((*frHndl)->fileState.sfType, nil);
  200.                 if (pref) {
  201.                     (*frHndl)->d.doc.fhInfo.structureRect = mDerefAPRF(pref)->structureRect;
  202.                     (*frHndl)->d.doc.fhInfo.contentRect   = mDerefAPRF(pref)->contentRect;
  203.                     (*frHndl)->d.doc.fhInfo.stdState      = mDerefAPRF(pref)->stdState;
  204.                     (*frHndl)->d.doc.fhInfo.userState     = mDerefAPRF(pref)->userState;
  205.                     attributes |= kwVisible;
  206.                     if (!mDerefAPRF(pref)->visible) attributes ^= kwVisible;
  207.                 }
  208.             }
  209.         }
  210.     }
  211.  
  212.     SetRect(&sizeInfo, 0, 0, 0, 0);
  213.     if ((proc == StaggerWindow) || (proc == OldLocWindow)) {
  214.         hDocSize = (*frHndl)->d.doc.fhInfo.hDocSize;
  215.         vDocSize = (*frHndl)->d.doc.fhInfo.vDocSize;
  216.         if (hDocSize) {
  217.             hDocSize += (*frHndl)->fileState.leftSidebar;
  218.             if (attributes & kwHScroll)
  219.                 if (vDocSize)
  220.                     vDocSize += 15;
  221.         }
  222.         if (vDocSize) {
  223.             vDocSize += (*frHndl)->fileState.topSidebar;
  224.             if (attributes & kwVScroll)
  225.                 if (hDocSize)
  226.                     hDocSize += 15;
  227.         }
  228.         SetRect(&sizeInfo, hDocSize, vDocSize, hDocSize, vDocSize);
  229.     }
  230.  
  231.     wkind = (attributes & (kwIsPalette | kwIsModalDialog));
  232.     if (behind) {
  233.         for (;;) {
  234.             if (!(behind = GetNextWindow(behind, 0))) break;
  235.                 /* break if behind all windows.  behind is nil, so that's what we have. */
  236.             if (!((WindowPeek)behind)->visible) continue;
  237.  
  238.             wwkind = kwIsDocument;
  239.             if (IsAppWindow(behind)) {
  240.                 ffrHndl = (FileRecHndl)GetWRefCon(behind);
  241.                 if (ffrHndl)
  242.                     wwkind  = ((*ffrHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog));
  243.             }
  244.  
  245.             if (wkind >= wwkind) {
  246.                 for (;;) {
  247.                     behind = GetPreviousWindow(behind);
  248.                     if (behind == (WindowPtr)-1)       break;
  249.                     if (((WindowPeek)behind)->visible) break;
  250.                 }
  251.                 break;
  252.             }
  253.         }
  254.     }
  255.  
  256.     oldPlaceRct = SetWindowPlacementRect(nil);
  257.     if (EmptyRect(&oldPlaceRct)) {
  258.  
  259.         if (attributes & kwSameMonitor) {
  260.             relatedWindow = nil;
  261.             for (; (relatedWindow = GetNextWindow(relatedWindow, (*frHndl)->fileState.sfType)) != nil;)
  262.                 if (((WindowPeek)relatedWindow)->visible) break;
  263.             if (!relatedWindow) {
  264.                 for (; (relatedWindow = GetNextWindow(relatedWindow, 0)) != nil;) {
  265.                     if (!((WindowPeek)relatedWindow)->visible) continue;
  266.                     if (((WindowPeek)relatedWindow)->windowKind >= 1000) {
  267.                         ffrHndl = (FileRecHndl)GetWRefCon(relatedWindow);
  268.                         if (ffrHndl) {
  269.                             wwkind = (*ffrHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  270.                             if (wkind == wwkind) break;
  271.                         }
  272.                     }
  273.                 }
  274.             }
  275.         }
  276.  
  277.         if ((!(attributes & kwSameMonitor)) || (!relatedWindow)) {
  278.             if (attributes & (kwColorMonitor | kwSecondaryMonitor)) {
  279.     
  280.                 if (gQDVersion > kQDOriginal) {
  281.                     rct = msrct = GetMainScreenRect();
  282.                     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  283.                         rct2 = (*device)->gdRect;
  284.                         if (TestDeviceAttribute(device, screenDevice) &&
  285.                             TestDeviceAttribute(device, screenActive)
  286.                         ) {
  287.                             pmap = (*device)->gdPMap;
  288.                             if (attributes & kwColorMonitor) {
  289.                                 if ((*pmap)->pixelSize > 1) {
  290.                                     rct = rct2;
  291.                                     if (!(rct.top | rct.left)) break;
  292.                                 }
  293.                             }
  294.                             else {
  295.                                 if (!EqualRect(&rct2, &msrct)) {
  296.                                     rct = rct2;
  297.                                     break;
  298.                                 }
  299.                             }
  300.                         }
  301.                     }
  302.                     if (EqualRect(&rct, &msrct))
  303.                         rct.top += GetMBarHeight();
  304.                     SetWindowPlacementRect(&rct);
  305.                 }
  306.             }
  307.         }
  308.     }
  309.  
  310.     window = GetSomeKindOfWindow(proc, (*frHndl)->fileState.windowID, nil, false, relatedWindow,
  311.                                  behind, true, sizeInfo, (long)frHndl);
  312.  
  313.     SetWindowPlacementRect(&oldPlaceRct);
  314.  
  315.     if (window) {
  316.         ((WindowPeek)window)->windowKind = 1000;        /* ID it as an AppsToGo window. */
  317.  
  318.         SetPort(window);
  319.         NewWindowTitle(window, nil);
  320.  
  321.         (*frHndl)->fileState.window = window;
  322.  
  323.         (*frHndl)->fileState.hArrowVal = 16;    /* Default arrow value is 16. */
  324.         (*frHndl)->fileState.vArrowVal = 16;
  325.  
  326.         if (!(*frHndl)->d.doc.fhInfo.hDocSize) {
  327.             h  = gOpenedWindowTemplate.boundsRect.right - gOpenedWindowTemplate.boundsRect.left;
  328.             h -= (*frHndl)->fileState.leftSidebar;    /* Default document size is */
  329.             if (attributes & kwVScroll)                /* content less leftSidebar */
  330.                 h -= 15;                            /* value less scrollbars.   */
  331.             (*frHndl)->d.doc.fhInfo.hDocSize = h;
  332.         }
  333.         if (!(*frHndl)->d.doc.fhInfo.vDocSize) {
  334.             v  = gOpenedWindowTemplate.boundsRect.bottom - gOpenedWindowTemplate.boundsRect.top;
  335.             v -= (*frHndl)->fileState.topSidebar;    /* We don't have to initialize the page */
  336.             if (attributes & kwHScroll)                /* values since the scrollbars won't be */
  337.                 v -= 15;                            /* active until the window is resized   */
  338.             (*frHndl)->d.doc.fhInfo.vDocSize = v;    /* or these values are set elsewhere.   */
  339.         }
  340.  
  341.         if (attributes & kwHScroll) {        /* Caller wants a horizontal scrollbar... */
  342.             ctlRect = window->portRect;
  343.             ctlRect.left += (*frHndl)->fileState.leftSidebar;
  344.             ctlRect.left += (*frHndl)->fileState.hScrollIndent;
  345.             --ctlRect.left;
  346.             ++ctlRect.right;
  347.             ctlRect.top = ++ctlRect.bottom - 16;
  348.             if (attributes & (kwHScrollLessGrow - kwHScroll +  kwGrowIcon))
  349.                 ctlRect.right -= 15;
  350.             OffsetRect(&ctlRect, 0, -16384);
  351.             ctl = NewControl(window, &ctlRect, "\p", true, 0, 0, 0, scrollBarProc, 0L);
  352.             if (ctl)
  353.                 (*frHndl)->fileState.hScroll = ctl;
  354.             else
  355.                 err = memFullErr;
  356.         }
  357.  
  358.         if (!err) {
  359.             if (attributes & kwVScroll) {        /* Caller wants a vertical scrollbar... */
  360.                 ctlRect = window->portRect;
  361.                 ctlRect.top += (*frHndl)->fileState.topSidebar;
  362.                 ctlRect.top += (*frHndl)->fileState.vScrollIndent;
  363.                 --ctlRect.top;
  364.                 ++ctlRect.bottom;
  365.                 ctlRect.left = ++ctlRect.right - 16;
  366.                 if (attributes & (kwVScrollLessGrow - kwVScroll +  kwGrowIcon))
  367.                     ctlRect.bottom -= 15;
  368.                 OffsetRect(&ctlRect, 0, -16384);
  369.                 ctl = NewControl(window, &ctlRect, "\p", true, 0, 0, 0, scrollBarProc, 0L);
  370.                 if (ctl)
  371.                     (*frHndl)->fileState.vScroll = ctl;
  372.                 else
  373.                     err = memFullErr;
  374.             }
  375.         }
  376.  
  377.         if (!err) {
  378.             err = DoInitContent(frHndl, window);
  379.             if (!err) {
  380.                 if (!((WindowPeek)window)->visible) {
  381.                     contRect = GetWindowContentRect(window);
  382.                     if (((WindowPeek)window)->spareFlag)
  383.                         userState = mDerefWStateData(window)->userState;
  384.                             /* Cache this.  ShowWindow offscreen messes it up.  We want to keep
  385.                             ** whatever it is because some other function may be tweeking stdState
  386.                             ** and userState so that window position and zoom state can be saved
  387.                             ** along with a document. */
  388.  
  389.                     MoveWindow(window, 16384, 16384, false);
  390.                         /* When an invisible window is added, it isn't the frontmost window.
  391.                         ** This causes a problem when we make it visible.  By moving it
  392.                         ** offscreen, we can make it visible without the user seeing that it
  393.                         ** isn't the top window. */
  394.  
  395.                     if (gPrintPage) {
  396.                         ShowWindow(window);                            /* Window now visible. */
  397.                         MoveWindow(window, 16384, 16384, true);        /* Window now on top.  */
  398.                     }    /* If we are printing, we want to leave the window offscreen, since we
  399.                         ** don't want it seen.  We do need a visible window when printing so
  400.                         ** PrintMonitor can get the document name. */
  401.  
  402.                     if (!gPrintPage) {
  403.                         if (attributes & kwVisible)
  404.                             ShowHide(window, true);
  405.                         CleanSendBehind(window, behind);
  406.                         MoveWindow(window, contRect.left, contRect.top, false);
  407.                     }
  408.  
  409.                     if (((WindowPeek)window)->spareFlag)
  410.                         mDerefWStateData(window)->userState = userState;
  411.                             /* The ShowWindow metrics we did cause the userState to change.  Put it
  412.                             ** back the way it was before we started messing around with the window. */
  413.  
  414.                     AdjustScrollBars(window);
  415.                 }
  416.             }
  417.         }
  418.         if (err) {
  419.             DisposeAnyWindow(window);
  420.             (*frHndl)->fileState.window = window = nil;
  421.         }
  422.     }
  423.     else err = gGetWindowErr;
  424.  
  425.     SetPort(oldPort);
  426.     if (retWindow)
  427.         *retWindow = window;
  428.  
  429.     return(err);
  430. }
  431.  
  432.  
  433.  
  434. /*****************************************************************************/
  435.  
  436.  
  437.  
  438. /* This function updates the window title to reflect the new document name.
  439. ** The new document name is stored in the fileState portion of the document.
  440. ** This is automatically set to 'Untitled # N' for new documents, and is
  441. ** updated when a user does a save-as.  If the window that is being opened
  442. ** should have the resource name, then set the new document name to an
  443. ** empty string prior to calling DoNewWindow.  When this is called by
  444. ** DoNewWindow, the SetWTitle will be suppressed. */
  445.  
  446. void    NewWindowTitle(WindowPtr window, StringPtr altTitle)
  447. {
  448.     FileRecHndl    frHndl;
  449.     Str255        wTitle;
  450.  
  451.     if (window) {
  452.         if (altTitle) {
  453.             pcpy(wTitle, altTitle);
  454.             SetWTitle(window, wTitle);
  455.         }
  456.         else {
  457.             frHndl = (FileRecHndl)GetWRefCon(window);
  458.             if (frHndl) {
  459.                 if (((WindowPeek)window)->windowKind >= 1000) {
  460.                     pcpy(wTitle, (*frHndl)->fileState.fss.name);
  461.                     if (*wTitle)
  462.                         SetWTitle(window, wTitle);
  463.                     else {
  464.                         if ((*frHndl)->fileState.refNum == kInvalRefNum) {
  465.                             GetWTitle(window, wTitle);
  466.                             if (*wTitle > 63) *wTitle = 63;
  467.                             pcpy((*frHndl)->fileState.fss.name, wTitle);
  468.                         }
  469.                     }
  470.                 }
  471.             }
  472.         }
  473.     }
  474. }
  475.  
  476.  
  477.  
  478. /*****************************************************************************/
  479.  
  480.  
  481.  
  482. /* Close all the windows.  This is called prior to quitting the application.
  483. ** This function returns true if all windows were closed.  The user may decide
  484. ** to abort a save, thus stopping the closing of the windows.  If the user
  485. ** does this, false will be returned, indicating that all windows were not
  486. ** closed after all. */
  487.  
  488. Boolean            DisposeAllWindows(void)
  489. {
  490.     WindowPtr    window;
  491.     FileRecHndl    frHndl;
  492.     long        attr;
  493.     TreeObjHndl    pref;
  494.     Boolean        newPref;
  495.  
  496.     gCursorPtr = nil;        /* Force recalc of cursor. */
  497.  
  498.     for (window = nil;;) {
  499.  
  500.         if (!window)
  501.             window = (WindowPtr)LMGetWindowList();
  502.         else
  503.             window = (WindowPtr)(((WindowPeek)window)->nextWindow);
  504.  
  505.         if (!window) break;        /* All out of windows to get rid of. */
  506.  
  507.         if (!IsDAWindow(window)) {
  508.             if (((WindowPeek)window)->windowKind >= 1000) {
  509.                 frHndl = (FileRecHndl)GetWRefCon(window);
  510.                 if (frHndl) {
  511.                     attr = (*frHndl)->fileState.attributes;
  512.                     if (
  513.                         (attr & kwOpenAtOldLoc) &&
  514.                         (attr & kwRuntimeOnlyDoc) &&
  515.                         (attr & kwHideOnClose)
  516.                     ) {
  517.                         if (gGetPreferenceProc) {
  518.                             pref = (*gGetPreferenceProc)((*frHndl)->fileState.sfType, &newPref);
  519.                             if (pref) {
  520.                                 mDerefAPRF(pref)->structureRect = GetWindowStructureRect(window);
  521.                                 mDerefAPRF(pref)->contentRect   = GetWindowContentRect(window);
  522.                                 mDerefAPRF(pref)->stdState      = mDerefWStateData(window)->stdState;
  523.                                 if (((WindowPeek)window)->spareFlag)
  524.                                     mDerefAPRF(pref)->userState = mDerefWStateData(window)->userState;
  525.                                 mDerefAPRF(pref)->visible = (((WindowPeek)window)->visible) ?
  526.                                     true : false;
  527.                             }
  528.                         }
  529.                         continue;
  530.                             /* Closing of all of the windows may be stopped at a dirty document,
  531.                             ** so don't close hide-on-close documents here. */
  532.                     }
  533.                 }
  534.             }
  535.         }
  536.  
  537.         if (!((WindowPeek)window)->visible) continue;
  538.             /* Invisible windows shouldn't be disposed of, since the user may cancel the quit,
  539.             ** and therefore the user will want windows around.  If a "hide on close" window
  540.             ** was closed, it was simply made invisible, so these windows are still actually
  541.             ** intact.  The user will have to show them again, but they still exist. */
  542.  
  543.         if (!DisposeOneWindow(window, kQuit)) return(false);
  544.             /* When DisposeOneWindow returns false, this means that the window
  545.             ** didn't close.  The only cause of this is if the window had a
  546.             ** document that needed saving, and the user cancelled the save.
  547.             ** If the windows succeed in getting closed, then we are
  548.             ** returned true. */
  549.  
  550.         window = nil;
  551.             /* The close of a window may have caused other window to close, so
  552.             ** start looking at windows from the beginning of the list.  This
  553.             ** guarantees that we are always looking at valid window records. */
  554.     }
  555.  
  556.     return(true);
  557. }
  558.  
  559.  
  560.  
  561. /*****************************************************************************/
  562.  
  563.  
  564.  
  565. /* Closes one window.  This window may be an application window, or it may be
  566. ** a system window.  If it is an application window, it may have a document
  567. ** that needs saving. */
  568.  
  569. Boolean    DisposeOneWindow(WindowPtr window, short saveMode)
  570. {
  571.     FileRecHndl    frHndl;
  572.     long        attr;
  573.     OSErr        err;
  574.     TreeObjHndl    pref;
  575.     Boolean        newPref;
  576.  
  577.     gCursorPtr = nil;        /* Force recalc of cursor. */
  578.  
  579.     if (window) {
  580.         if (!IsDAWindow(window)) {
  581.             /* First, if the window is an application window, try saving
  582.             ** the document.  Remember that the user may cancel the save. */
  583.  
  584.             if (((WindowPeek)window)->windowKind >= 1000) {
  585.                 frHndl = (FileRecHndl)GetWRefCon(window);
  586.                 if (frHndl) {
  587.                     attr = (*frHndl)->fileState.attributes;
  588.                     if (
  589.                         (attr & kwOpenAtOldLoc) &&
  590.                         (attr & kwRuntimeOnlyDoc) &&
  591.                         (!(attr & kwHideOnClose))
  592.                     ) {
  593.                         if (gGetPreferenceProc) {
  594.                             pref = (*gGetPreferenceProc)((*frHndl)->fileState.sfType, &newPref);
  595.                             if (pref) {
  596.                                 mDerefAPRF(pref)->structureRect = GetWindowStructureRect(window);
  597.                                 mDerefAPRF(pref)->contentRect   = GetWindowContentRect(window);
  598.                                 mDerefAPRF(pref)->stdState      = mDerefWStateData(window)->stdState;
  599.                                 if (((WindowPeek)window)->spareFlag)
  600.                                     mDerefAPRF(pref)->userState = mDerefWStateData(window)->userState;
  601.                                 mDerefAPRF(pref)->visible = (((WindowPeek)window)->visible) ?
  602.                                     true : false;
  603.                             }
  604.                         }
  605.                     }
  606.  
  607.                     if (attr & kwHideOnClose) {
  608.                         if (gHideWindowProc) {
  609.                             err = (*gHideWindowProc)(frHndl, window);
  610.                             if (err)
  611.                                 return(false);
  612.                         }
  613.                         HideWindow(window);
  614.                         HiliteWindows();
  615.                         WindowGoneFixup(window);
  616.                         return(true);
  617.                     }
  618.  
  619.                     if (!((*frHndl)->fileState.attributes & kwRuntimeOnlyDoc)) {
  620.                         if (IsAppWindow(window)) {
  621.                             err = SaveDocument(frHndl, window, saveMode);
  622.                             if (err) {
  623.                                 if (err != userCanceledErr) {
  624.                                     gDialogErr = err;
  625.                                     NewDocumentWindow(nil, 'ERR#', false);
  626.                                 }
  627.                                 return(false);
  628.                             }        /* Stop closing windows on error or user cancel. */
  629.                         }
  630.                     }
  631.  
  632.                     err = DoFreeWindow(frHndl, window);
  633.                     if (err) return(false);
  634.  
  635.                     DisposeDocument(frHndl);
  636.                         /* If everything is cool, dispose of the document. */
  637.                 }
  638.             }
  639.         }
  640.  
  641.         DisposeAnyWindow(window);
  642.         HiliteWindows();
  643.         WindowGoneFixup(window);
  644.             /* Give the application a chance to do any related tasks. */
  645.  
  646.     }
  647.  
  648.     return(true);
  649. }
  650.  
  651.  
  652.  
  653. /*****************************************************************************/
  654.  
  655.  
  656.  
  657. WindowPtr    SetFilePort(FileRecHndl frHndl)
  658. {
  659.     WindowPtr    oldPort;
  660.  
  661.     GetPort(&oldPort);
  662.     if (frHndl)
  663.         SetPort((*frHndl)->fileState.window);
  664.     return(oldPort);
  665. }
  666.  
  667.  
  668.  
  669. /*****************************************************************************/
  670.  
  671.  
  672.  
  673. void    DoResizeWindow(WindowPtr window, short oldh, short oldv)
  674. {
  675.     FileRecHndl        frHndl;
  676.     WindowPtr        oldPort;
  677.     long            attributes;
  678.     Boolean            growIconSpace;
  679.     Rect            portRct, rct;
  680.     ControlHandle    hScroll, vScroll;
  681.     RgnHandle        updateRgn;
  682.     short            i;
  683.  
  684.     gCursorPtr = nil;        /* Force recalc of cursor. */
  685.  
  686.     if (!window)                                     return;
  687.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  688.  
  689.     oldPort       = SetFilePort(frHndl);
  690.     attributes    = (*frHndl)->fileState.attributes;
  691.     growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
  692.         /* growIconSpace true if window has grow icon or a blank space for one. */
  693.  
  694.     SetOrigin(0, 0);
  695.     portRct = window->portRect;
  696.  
  697.     if (growIconSpace) {
  698.         rct.left = (rct.right  = oldh) - 15;
  699.         rct.top  = (rct.bottom = oldv) - 15;
  700.         EraseRect(&rct);
  701.         InvalRect(&rct);
  702.         rct = portRct;
  703.         rct.left = rct.right  - 15;
  704.         rct.top  = rct.bottom - 15;
  705.         EraseRect(&rct);
  706.     }
  707.  
  708.     SetOrigin(0, -16384);
  709.     hScroll = (*frHndl)->fileState.hScroll;
  710.     if (hScroll) {
  711.         HideControl(hScroll);
  712.         rct = (*hScroll)->contrlRect;
  713.         MoveControl(hScroll, rct.left, portRct.bottom - 15 - 16384);
  714.         SizeControl(hScroll, rct.right - rct.left + (portRct.right - portRct.left - oldh), 16);
  715.     }
  716.     vScroll = (*frHndl)->fileState.vScroll;
  717.     if (vScroll) {
  718.         HideControl(vScroll);
  719.         rct = (*vScroll)->contrlRect;
  720.         MoveControl(vScroll, portRct.right - 15, rct.top);
  721.         SizeControl(vScroll, 16, rct.bottom - rct.top + (portRct.bottom - portRct.top - oldv));
  722.     }
  723.  
  724.     i = (*frHndl)->fileState.hScrollIndent;
  725.     if (i) {
  726.         rct       = window->portRect;
  727.         rct.right = --i;
  728.         rct.top   = rct.bottom - 15;
  729.         InvalRect(&rct);
  730.         rct.bottom = window->portRect.top + oldv;
  731.         rct.top    = rct.bottom - 15;
  732.         EraseRect(&rct);
  733.         InvalRect(&rct);
  734.     }
  735.  
  736.     i = (*frHndl)->fileState.vScrollIndent;
  737.     if (i) {
  738.         rct        = window->portRect;
  739.         rct.bottom = --i;
  740.         rct.left   = rct.right - 15;
  741.         InvalRect(&rct);
  742.         rct.right  = window->portRect.left + oldh;
  743.         rct.left   = rct.right - 15;
  744.         EraseRect(&rct);
  745.         InvalRect(&rct);
  746.     }
  747.  
  748.     AdjustScrollBars(window);
  749.  
  750.     if (hScroll)
  751.         ShowControl(hScroll);
  752.     if (vScroll)
  753.         ShowControl(vScroll);
  754.  
  755.     SetOrigin(0, 0);
  756.     if (attributes & kwGrowIcon)
  757.         DoDrawGrowIcon(window, false, false);
  758.  
  759.     BeginContent(window);
  760.     DoResizeContent(window, oldh, oldv);
  761.     updateRgn = NewRgn();
  762.     CopyRgn(((WindowPeek)window)->updateRgn, updateRgn);
  763.     EndContent(window);
  764.     UnionRgn(updateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
  765.     DisposeRgn(updateRgn);
  766.  
  767.     SetPort(oldPort);
  768. }
  769.  
  770.  
  771.  
  772. /*****************************************************************************/
  773.  
  774.  
  775.  
  776. /* This function returns the difference between the old window size and the new window
  777. ** size.  Pass in the old window size, and this function looks up the current size,
  778. ** gets the difference, and returns it. */
  779.  
  780. void    GetWindowChange(WindowPtr window, short oldh, short oldv, short *dx, short *dy)
  781. {
  782.     *dx = (window->portRect.right  - window->portRect.left) - oldh;
  783.     *dy = (window->portRect.bottom - window->portRect.top)  - oldv;
  784.  
  785. }
  786.  
  787.  
  788.  
  789. /*****************************************************************************/
  790.  
  791.  
  792.  
  793. void    DoUpdateSeparate(WindowPtr window, RgnHandle *contRgn, RgnHandle *frameRgn)
  794. {
  795.     RgnHandle    urgn, wrgn;
  796.  
  797.     *contRgn = *frameRgn = nil;
  798.     if (!window) return;
  799.  
  800.     urgn = DoCalcFrameRgn(window);
  801.     wrgn = NewRgn();
  802.  
  803.     DiffRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
  804.     if (!EmptyRgn(wrgn)) {
  805.         *contRgn = wrgn;
  806.         wrgn = NewRgn();
  807.     }
  808.     SectRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
  809.  
  810.     if (!EmptyRgn(wrgn))
  811.         *frameRgn = wrgn;
  812.     else
  813.         DisposeRgn(wrgn);
  814.  
  815.     DisposeRgn(urgn);
  816. }
  817.  
  818.  
  819.  
  820. /*****************************************************************************/
  821.  
  822.  
  823.  
  824. void    BeginContent(WindowPtr window)
  825. {
  826.     RgnHandle    updateRgn, frameRgn;
  827.     Point        contOrg;
  828.  
  829.     if (!gBeginUpdateNested++) {
  830.         GetPort(&gOldPort);
  831.         CopyRgn(updateRgn = ((WindowPeek)window)->updateRgn, gKeepUpdateRgn = NewRgn());
  832.         frameRgn = DoCalcFrameRgn(window);
  833.         DiffRgn(((WindowPeek)window)->contRgn, frameRgn, updateRgn);
  834.         DisposeRgn(frameRgn);
  835.         BeginUpdate(window);
  836.     }
  837.     SetPort(window);
  838.     GetContentOrigin(window, &contOrg);
  839.     SetOrigin(contOrg.h, contOrg.v);
  840. }
  841.  
  842.  
  843.  
  844. /*****************************************************************************/
  845.  
  846.  
  847.  
  848. void    EndContent(WindowPtr window)
  849. {
  850.     if (gBeginUpdateNested) {
  851.         if (!--gBeginUpdateNested) {
  852.             EndUpdate(window);
  853.             if (gKeepUpdateRgn) {
  854.                 UnionRgn(gKeepUpdateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
  855.                 DisposeRgn(gKeepUpdateRgn);
  856.                 SetPort(gOldPort);
  857.                 gKeepUpdateRgn = nil;
  858.             }
  859.         }
  860.     }
  861. }
  862.  
  863.  
  864.  
  865. /*****************************************************************************/
  866.  
  867.  
  868.  
  869. void    BeginFrame(WindowPtr window)
  870. {
  871.     RgnHandle    updateRgn, frameRgn, scrollRgn;
  872.  
  873.     if (!gBeginUpdateNested++) {
  874.         GetPort(&gOldPort);
  875.         CopyRgn(updateRgn = ((WindowPeek)window)->updateRgn, gKeepUpdateRgn = NewRgn());
  876.         frameRgn  = DoCalcFrameRgn(window);
  877.         scrollRgn = DoCalcScrollRgn(window);
  878.         DiffRgn(frameRgn, scrollRgn, frameRgn);
  879.         DisposeRgn(scrollRgn);
  880.         SectRgn(((WindowPeek)window)->contRgn, frameRgn, updateRgn);
  881.         DisposeRgn(frameRgn);
  882.         BeginUpdate(window);
  883.     }
  884.     SetPort(window);
  885.     SetOrigin(-16384, 0);
  886. }
  887.  
  888.  
  889.  
  890. /*****************************************************************************/
  891.  
  892.  
  893.  
  894. void    EndFrame(WindowPtr window)
  895. {
  896.     EndContent(window);
  897. }
  898.  
  899.  
  900.  
  901. /*****************************************************************************/
  902.  
  903.  
  904.  
  905. void    AdjustScrollBars(WindowPtr window)
  906. {
  907.     FileRecHndl            frHndl;
  908.     WindowPtr            oldPort;
  909.     ControlHandle        hScroll, vScroll;
  910.     Rect                portRct;
  911.     Point                keepOrg;
  912.     short                h, v, maxVal, val;
  913.     DocScrollBarProc    proc;
  914.  
  915.     if (!window)                                     return;
  916.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  917.  
  918.     oldPort = SetFilePort(frHndl);
  919.     portRct = window->portRect;
  920.  
  921.     keepOrg.h = portRct.left;
  922.     keepOrg.v = portRct.top;
  923.  
  924.     portRct.left += (*frHndl)->fileState.leftSidebar;
  925.     portRct.top  += (*frHndl)->fileState.topSidebar;
  926.  
  927.     hScroll = (*frHndl)->fileState.hScroll;
  928.     vScroll = (*frHndl)->fileState.vScroll;
  929.  
  930.     SetOrigin(0, -16384);
  931.  
  932.     if ((maxVal = (*frHndl)->d.doc.fhInfo.hDocSize) > 0) {
  933.         h = portRct.right - portRct.left;
  934.         if (vScroll)
  935.             h -= 15;
  936.         maxVal -= h;
  937.         if (maxVal < 0)
  938.             maxVal = 0;
  939.         if (hScroll) {
  940.             proc = (DocScrollBarProc)GetControlReference(hScroll);
  941.             if (proc)
  942.                 (*proc)(frHndl, hScroll, kscrollHAdjust, h);
  943.             else {
  944.                 if (maxVal < (val = GetControlValue(hScroll)))
  945.                     maxVal = val;
  946.                 if ((*hScroll)->contrlMax != maxVal) {
  947.                     (*hScroll)->contrlMax = maxVal;
  948.                     DoDraw1Control(hScroll, true);
  949.                 }
  950.                 h -= (val = (*frHndl)->fileState.hArrowVal);
  951.                 if (h < val)
  952.                     h = val;
  953.                 (*frHndl)->fileState.hPageVal = h;
  954.             }
  955.         }
  956.     }
  957.  
  958.     if ((maxVal = (*frHndl)->d.doc.fhInfo.vDocSize) > 0) {
  959.         v = portRct.bottom - portRct.top;
  960.         if (hScroll)
  961.             v -= 15;
  962.         maxVal -= v;
  963.         if (maxVal < 0)
  964.             maxVal = 0;
  965.         if (vScroll) {
  966.             proc = (DocScrollBarProc)GetControlReference(vScroll);
  967.             if (proc)
  968.                 (*proc)(frHndl, vScroll, kscrollVAdjust, v);
  969.             else {
  970.                 if (maxVal < (val = GetControlValue(vScroll)))
  971.                     maxVal = val;
  972.                 if ((*vScroll)->contrlMax != maxVal) {
  973.                     (*vScroll)->contrlMax = maxVal;
  974.                     DoDraw1Control(vScroll, true);
  975.                 }
  976.                 v -= (val = (*frHndl)->fileState.vArrowVal);
  977.                 if (v < val)
  978.                     v = val;
  979.                 (*frHndl)->fileState.vPageVal = v;
  980.             }
  981.         }
  982.     }
  983.  
  984.     SetOrigin(keepOrg.h, keepOrg.v);
  985.     SetPort(oldPort);
  986. }
  987.  
  988.  
  989.  
  990. /*****************************************************************************/
  991.  
  992.  
  993.  
  994. void    GetContentOrigin(WindowPtr window, Point *contOrg)
  995. {
  996.     FileRecHndl            frHndl;
  997.     ControlHandle        ctl;
  998.     DocScrollBarProc    proc;
  999.  
  1000.     contOrg->h = contOrg->v = 0;
  1001.  
  1002.     if (window) {
  1003.         if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  1004.         ctl = (*frHndl)->fileState.hScroll;
  1005.         if (ctl) {
  1006.             contOrg->h = GetControlValue(ctl);
  1007.             proc = (DocScrollBarProc)GetControlReference(ctl);
  1008.             if (proc)
  1009.                 contOrg->h = (*proc)(frHndl, ctl, kscrollGetHOrigin, 0);
  1010.         }
  1011.         ctl = (*frHndl)->fileState.vScroll;
  1012.         if (ctl) {
  1013.             contOrg->v = GetControlValue(ctl);
  1014.             proc = (DocScrollBarProc)GetControlReference(ctl);
  1015.             if (proc)
  1016.                 contOrg->v = (*proc)(frHndl, ctl, kscrollGetVOrigin, 0);
  1017.         }
  1018.         contOrg->h -= (*frHndl)->fileState.leftSidebar;
  1019.         contOrg->v -= (*frHndl)->fileState.topSidebar;
  1020.     }
  1021. }
  1022.  
  1023.  
  1024.  
  1025. /*****************************************************************************/
  1026.  
  1027.  
  1028.  
  1029. void    SetContentOrigin(WindowPtr window, long newh, long newv)
  1030. {
  1031.     FileRecHndl        frHndl;
  1032.     WindowPtr        oldPort;
  1033.     ControlHandle    hScroll, vScroll;
  1034.     short            topSide, leftSide, max, dh, dv;
  1035.     Point            old, contOrg;
  1036.     RgnHandle        updateRgn;
  1037.     Rect            contRct;
  1038.  
  1039.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1040.  
  1041.     if (!window)                                     return;
  1042.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  1043.  
  1044.     oldPort = SetFilePort(frHndl);
  1045.     hScroll = (*frHndl)->fileState.hScroll;
  1046.     vScroll = (*frHndl)->fileState.vScroll;
  1047.     GetContentOrigin(window, &old);
  1048.     GetContentRect(window, &contRct);
  1049.  
  1050.     SetOrigin(0, -16384);
  1051.     topSide  = (*frHndl)->fileState.topSidebar;
  1052.     leftSide = (*frHndl)->fileState.leftSidebar;
  1053.  
  1054.     if (!hScroll)
  1055.         newh = kwNoChange;
  1056.     if (newh != kwNoChange) {
  1057.         if (newh != kwBotScroll)
  1058.             newh += leftSide;
  1059.         if (newh < 0)
  1060.             newh = 0;
  1061.         if (newh > (max = GetControlMaximum(hScroll)))
  1062.             newh = max;
  1063.         if ((*hScroll)->contrlValue != newh) {
  1064.             (*hScroll)->contrlValue = newh;
  1065.             DoDraw1Control(hScroll, true);
  1066.         }
  1067.         newh -= leftSide;
  1068.     }
  1069.  
  1070.     if (!vScroll)
  1071.         newv = kwNoChange;
  1072.     if (newv != kwNoChange) {
  1073.         if (newv != kwBotScroll)
  1074.             newv += topSide;
  1075.         if (newv < 0)
  1076.             newv = 0;
  1077.         if (newv > (max = GetControlMaximum(vScroll)))
  1078.             newv = max;
  1079.         if ((*vScroll)->contrlValue != newv) {
  1080.             (*vScroll)->contrlValue = newv;
  1081.             DoDraw1Control(vScroll, true);
  1082.         }
  1083.         newv -= topSide;
  1084.     }
  1085.  
  1086.     AdjustScrollBars(window);
  1087.  
  1088.     dh = dv = 0;
  1089.     if (newh != kwNoChange)
  1090.         dh = old.h - newh;
  1091.     if (newv != kwNoChange)
  1092.         dv = old.v - newv;
  1093.  
  1094.     BeginContent(window);
  1095.     ScrollRect(&(window->portRect), dh, dv, updateRgn = NewRgn());
  1096.     EndContent(window);
  1097.  
  1098.     OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
  1099.         /* We want to add the scrolled-in area into the updateRgn.  We
  1100.         ** also want to keep the old area.  The old update area is
  1101.         ** no longer mapped to the same location, due to the scroll,
  1102.         ** so offset it by the amount scrolled.  Once it is offset, we
  1103.         ** can add our new update portion to the updateRgn. */
  1104.  
  1105.     GetContentOrigin(window, &contOrg);
  1106.     SetOrigin(contOrg.h, contOrg.v);
  1107.     InvalRgn(updateRgn);
  1108.     DisposeRgn(updateRgn);
  1109.  
  1110.     SetOrigin(old.h, old.v);
  1111.     SetPort(oldPort);                /* Put things back the way we found them. */
  1112.  
  1113.     DoScrollFrame(window, dh, dv);    /* There may be changes in the frame due to scrolling. */
  1114.  
  1115.     DoSetCursor(nil);                /* Cursor region may be invalid due to
  1116.                                     ** content being scrolled.  Force it to
  1117.                                     ** be recalculated. */
  1118. }
  1119.  
  1120.  
  1121.  
  1122. /*****************************************************************************/
  1123.  
  1124.  
  1125.  
  1126. void    GetContentRect(WindowPtr window, Rect *contRct)
  1127. {
  1128.     FileRecHndl        frHndl;
  1129.  
  1130.     SetRect(contRct, 0, 0, 0, 0);
  1131.  
  1132.     if (window) {
  1133.         if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  1134.         *contRct = window->portRect;
  1135.         if ((*frHndl)->fileState.hScroll)
  1136.             contRct->bottom -= 15;
  1137.         if ((*frHndl)->fileState.vScroll)
  1138.             contRct->right  -= 15;
  1139.         contRct->top  += (*frHndl)->fileState.topSidebar;
  1140.         contRct->left += (*frHndl)->fileState.leftSidebar;
  1141.     }
  1142. }
  1143.  
  1144.  
  1145.  
  1146. /*****************************************************************************/
  1147.  
  1148.  
  1149.  
  1150. void    SetDocSize(FileRecHndl frHndl, long hSize, long vSize)
  1151. {
  1152.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1153.  
  1154.     if (frHndl) {
  1155.         if (hSize >= 0)
  1156.             (*frHndl)->d.doc.fhInfo.hDocSize = hSize;
  1157.         if (vSize >= 0)
  1158.             (*frHndl)->d.doc.fhInfo.vDocSize = vSize;
  1159.         AdjustScrollBars((*frHndl)->fileState.window);
  1160.     }
  1161. }
  1162.  
  1163.  
  1164.  
  1165. /*****************************************************************************/
  1166.  
  1167.  
  1168.  
  1169. void    SetSidebarSize(FileRecHndl frHndl, short newLeft, short newTop)
  1170. {
  1171.     WindowPtr            oldPort, window;
  1172.     Rect                portRct, rct;
  1173.     Point                contOrg;
  1174.     short                oldLeft, oldTop, dh, dv;
  1175.     ControlHandle        ctl;
  1176.     RgnHandle            updateRgn;
  1177.     DrawFrameProcPtr    proc;
  1178.  
  1179.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1180.  
  1181.     window = (*frHndl)->fileState.window;
  1182.     if (window) {
  1183.         oldPort = SetFilePort(frHndl);
  1184.         portRct = window->portRect;
  1185.         SetOrigin(0, -16384);        /* Prepare to modify (redraw) document scrollbars. */
  1186.     }
  1187.  
  1188.     oldLeft = (*frHndl)->fileState.leftSidebar;
  1189.     oldTop  = (*frHndl)->fileState.topSidebar;
  1190.  
  1191.     dh = 0;
  1192.     if (newLeft != kwNoChange) {
  1193.         ctl = (*frHndl)->fileState.hScroll;
  1194.         if (ctl) {
  1195.             HideControl(ctl);
  1196.             rct = (*ctl)->contrlRect;
  1197.             rct.left += (newLeft - oldLeft);
  1198.             MoveControl(ctl, rct.left, rct.top);
  1199.             SizeControl(ctl, rct.right - rct.left, 16);
  1200.             ShowControl(ctl);
  1201.         }
  1202.         dh = newLeft - oldLeft;
  1203.     }
  1204.  
  1205.     dv = 0;
  1206.     if (newTop != kwNoChange) {
  1207.         ctl = (*frHndl)->fileState.vScroll;
  1208.         if (ctl) {
  1209.             HideControl(ctl);
  1210.             rct = (*ctl)->contrlRect;
  1211.             rct.top += (newTop - oldTop);
  1212.             MoveControl(ctl, rct.left, rct.top);
  1213.             SizeControl(ctl, 16, rct.bottom - rct.top);
  1214.             ShowControl(ctl);
  1215.         }
  1216.         dv = newTop - oldTop;
  1217.     }
  1218.  
  1219.     if (dh < 0)
  1220.         (*frHndl)->fileState.leftSidebar = newLeft;
  1221.     if (dv < 0)
  1222.         (*frHndl)->fileState.topSidebar  = newTop;
  1223.  
  1224.     if (window) {
  1225.         BeginContent(window);
  1226.         ScrollRect(&(window->portRect), dh, dv, updateRgn = NewRgn());
  1227.         EndContent(window);
  1228.     }
  1229.  
  1230.     if (dh)
  1231.         (*frHndl)->fileState.leftSidebar = newLeft;
  1232.     if (dv)
  1233.         (*frHndl)->fileState.topSidebar  = newTop;
  1234.  
  1235.     if (window) {
  1236.         AdjustScrollBars(window);
  1237.  
  1238.         proc = (*frHndl)->fileState.drawFrameProc;
  1239.         if (proc) {
  1240.             SetOrigin(-16384, 0);
  1241.             (*proc)(frHndl, window, false);        /* Draw the application's portion of the frame. */
  1242.         }
  1243.  
  1244.         OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
  1245.             /* We want to add the scrolled-in area into the updateRgn.  We
  1246.             ** also want to keep the old area.  The old update area is
  1247.             ** no longer mapped to the same location, due to the scroll,
  1248.             ** so offset it by the amount scrolled.  Once it is offset, we
  1249.             ** can add our new update portion to the updateRgn. */
  1250.         GetContentOrigin(window, &contOrg);
  1251.         SetOrigin(contOrg.h, contOrg.v);
  1252.         InvalRgn(updateRgn);
  1253.         DisposeRgn(updateRgn);
  1254.  
  1255.         SetOrigin(portRct.left, portRct.top);
  1256.         SetPort(oldPort);
  1257.  
  1258.         DoScrollFrame(window, dh, dv);        /* There may be changes in the frame due to scrolling. */
  1259.     }
  1260. }
  1261.  
  1262.  
  1263.  
  1264. /*****************************************************************************/
  1265.  
  1266.  
  1267.  
  1268. void    SetScrollIndentSize(FileRecHndl frHndl, short newh, short newv)
  1269. {
  1270.     WindowPtr            oldPort, window;
  1271.     Rect                portRct, rct;
  1272.     short                oldh, oldv;
  1273.     ControlHandle        ctl;
  1274.     DrawFrameProcPtr    proc;
  1275.  
  1276.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1277.  
  1278.     oldPort = SetFilePort(frHndl);
  1279.     GetPort(&window);
  1280.     portRct = window->portRect;
  1281.     SetOrigin(0, -16384);
  1282.  
  1283.     oldh = (*frHndl)->fileState.hScrollIndent;
  1284.     oldv = (*frHndl)->fileState.vScrollIndent;
  1285.  
  1286.     if (newh != kwNoChange) {
  1287.         ctl = (*frHndl)->fileState.hScroll;
  1288.         if (ctl) {
  1289.             HideControl(ctl);
  1290.             rct = (*ctl)->contrlRect;
  1291.             rct.left += (newh - oldh);
  1292.             MoveControl(ctl, rct.left, rct.top);
  1293.             SizeControl(ctl, rct.right - rct.left, 16);
  1294.             ShowControl(ctl);
  1295.         }
  1296.         (*frHndl)->fileState.hScrollIndent = newh;
  1297.     }
  1298.  
  1299.     if (newv != kwNoChange) {
  1300.         ctl = (*frHndl)->fileState.vScroll;
  1301.         if (ctl) {
  1302.             HideControl(ctl);
  1303.             rct = (*ctl)->contrlRect;
  1304.             rct.top += (newv - oldv);
  1305.             MoveControl(ctl, rct.left, rct.top);
  1306.             SizeControl(ctl, 16, rct.bottom - rct.top);
  1307.             ShowControl(ctl);
  1308.         }
  1309.         (*frHndl)->fileState.vScrollIndent = newv;
  1310.     }
  1311.  
  1312.     proc = (*frHndl)->fileState.drawFrameProc;
  1313.     if (proc) {
  1314.         SetOrigin(-16384, 0);
  1315.         (*proc)(frHndl, window, false);        /* Draw the application's portion of the frame. */
  1316.     }
  1317.  
  1318.     SetOrigin(portRct.left, portRct.top);
  1319.     SetPort(oldPort);
  1320. }
  1321.  
  1322.  
  1323.  
  1324. /*****************************************************************************/
  1325.  
  1326.  
  1327.  
  1328. FileRecHndl    GetNextDocument(WindowPtr window, OSType sftype)
  1329. {
  1330.     if (!(window = GetNextWindow(window, sftype))) return(nil);
  1331.     if (IsDAWindow(window))                           return(nil);
  1332.  
  1333.     return((FileRecHndl)GetWRefCon(window));
  1334. }
  1335.  
  1336.  
  1337.  
  1338. /*****************************************************************************/
  1339.  
  1340.  
  1341.  
  1342. WindowPtr    GetNextWindow(WindowPtr window, OSType sftype)
  1343. {
  1344.     WindowPeek    wpeek;
  1345.     FileRecHndl    frHndl;
  1346.  
  1347.     if (window == (WindowPtr)-1)
  1348.         window = nil;
  1349.  
  1350.     if (!window)
  1351.         wpeek = LMGetWindowList();
  1352.     else
  1353.         wpeek = ((WindowPeek)window)->nextWindow;
  1354.  
  1355.     for (; wpeek; wpeek = wpeek->nextWindow) {
  1356.  
  1357.         if (IsDAWindow((WindowPtr)wpeek))
  1358.             if (!sftype)
  1359.                 return((WindowPtr)wpeek);
  1360.  
  1361.         if (wpeek->windowKind < 1000) continue;
  1362.  
  1363.         if (!sftype) break;
  1364.             /* Request is for any window.  We have a window, so break. */
  1365.  
  1366.         frHndl = (FileRecHndl)GetWRefCon((WindowPtr)wpeek);
  1367.         if (!frHndl) continue;
  1368.  
  1369.         if ((*frHndl)->fileState.sfType == sftype) break;        /* Bingo. */
  1370.             /* The sfType field is the first 4 bytes in the refcon handle.  If you don't
  1371.             ** want to use the application framework completely, but you still want this
  1372.             ** function, then all you have to do is place an identifier in the first 4
  1373.             ** bytes of the refcon handle. */
  1374.     }
  1375.  
  1376.     return((WindowPtr)wpeek);
  1377. }
  1378.  
  1379.  
  1380.  
  1381. /*****************************************************************************/
  1382.  
  1383.  
  1384.  
  1385. WindowPtr    GetPreviousWindow(WindowPtr window)
  1386. {
  1387.     WindowPeek    wpeek;
  1388.     WindowPtr    lastWindow;
  1389.  
  1390.     if (window == (WindowPtr)-1) return((WindowPtr)-1);
  1391.     wpeek = LMGetWindowList();
  1392.  
  1393.     for (lastWindow = (WindowPtr)-1; wpeek; wpeek = wpeek->nextWindow) {
  1394.         if (window == (WindowPtr)wpeek) break;
  1395.         lastWindow = (WindowPtr)wpeek;
  1396.     }
  1397.  
  1398.     return(lastWindow);
  1399. }
  1400.  
  1401.  
  1402.  
  1403. /*****************************************************************************/
  1404.  
  1405.  
  1406.  
  1407. void    DoZoomWindow(WindowPtr window, EventRecord *event, short zoomDir)
  1408. {
  1409.     Boolean        doit;
  1410.     Rect        old;
  1411.     FileRecHndl    frHndl;
  1412.     short        hDocSize, vDocSize;
  1413.  
  1414.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1415.  
  1416.     if (!window)                                     return;
  1417.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  1418.  
  1419.     doit = true;
  1420.     if (event)
  1421.         doit = TrackBox(window, event->where, zoomDir);
  1422.  
  1423.     if (doit) {
  1424.         old       = GetWindowContentRect(window);
  1425.         hDocSize  = (*frHndl)->d.doc.fhInfo.hDocSize;
  1426.         hDocSize += (*frHndl)->fileState.leftSidebar;
  1427.         if ((*frHndl)->fileState.vScroll)
  1428.             hDocSize += 15;
  1429.         vDocSize  = (*frHndl)->d.doc.fhInfo.vDocSize;
  1430.         vDocSize += (*frHndl)->fileState.topSidebar;
  1431.         if ((*frHndl)->fileState.hScroll)
  1432.             vDocSize += 15;
  1433.  
  1434.         if (hDocSize < (*frHndl)->fileState.windowSizeBounds.left)
  1435.             hDocSize = (*frHndl)->fileState.windowSizeBounds.left;
  1436.         if (vDocSize < (*frHndl)->fileState.windowSizeBounds.top)
  1437.             vDocSize = (*frHndl)->fileState.windowSizeBounds.top;
  1438.  
  1439.         ZoomToWindowDevice(window, hDocSize, vDocSize, zoomDir, false);
  1440.         DoResizeWindow(window, old.right - old.left, old.bottom - old.top);
  1441.     }
  1442. }
  1443.  
  1444.  
  1445.  
  1446. /*****************************************************************************/
  1447. /*****************************************************************************/
  1448.  
  1449.  
  1450.  
  1451. RgnHandle    DoCalcFrameRgn(WindowPtr window)
  1452. {
  1453.     FileRecHndl            frHndl;
  1454.     WindowPtr            oldPort;
  1455.     RgnHandle            urgn, wrgn;
  1456.     short                i;
  1457.     Rect                rct;
  1458.     Point                l2g;
  1459.     CalcFrameRgnProcPtr    proc;
  1460.  
  1461.     urgn = NewRgn();
  1462.     if (!window)                                     return(urgn);
  1463.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return(urgn);
  1464.  
  1465.     oldPort = SetFilePort(frHndl);
  1466.     SetOrigin(0, 0);
  1467.  
  1468.     proc = (*frHndl)->fileState.calcFrameRgnProc;
  1469.     if (proc)
  1470.         (*proc)(frHndl, window, urgn);
  1471.  
  1472.     wrgn = NewRgn();
  1473.     for (i = 0; i < 2; ++i) {
  1474.         rct = window->portRect;
  1475.         if (i)
  1476.             rct.bottom = (*frHndl)->fileState.topSidebar;
  1477.         else
  1478.             rct.right  = (*frHndl)->fileState.leftSidebar;
  1479.         RectRgn(wrgn, &rct);
  1480.         UnionRgn(urgn, wrgn, urgn);
  1481.     }
  1482.     DisposeRgn(wrgn);
  1483.  
  1484.     l2g.h = l2g.v = 0;
  1485.     LocalToGlobal(&l2g);
  1486.     OffsetRgn(urgn, l2g.h, l2g.v);
  1487.  
  1488.     wrgn = DoCalcScrollRgn(window);
  1489.     UnionRgn(urgn, wrgn, urgn);
  1490.     DisposeRgn(wrgn);
  1491.  
  1492.     SetPort(oldPort);
  1493.     return(urgn);
  1494. }
  1495.  
  1496.  
  1497.  
  1498. /*****************************************************************************/
  1499.  
  1500.  
  1501.  
  1502. RgnHandle    DoCalcScrollRgn(WindowPtr window)
  1503. {
  1504.     FileRecHndl            frHndl;
  1505.     WindowPtr            oldPort;
  1506.     RgnHandle            urgn, wrgn;
  1507.     short                i;
  1508.     long                attributes;
  1509.     Boolean                growIconSpace;
  1510.     Rect                rct;
  1511.     Point                l2g;
  1512.     ControlHandle        ctl;
  1513.  
  1514.     urgn = NewRgn();
  1515.     if (!window) return(urgn);
  1516.     if (!window)                                     return(urgn);
  1517.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return(urgn);
  1518.  
  1519.     oldPort = SetFilePort(frHndl);
  1520.     SetOrigin(0, 0);
  1521.  
  1522.     attributes    = (*frHndl)->fileState.attributes;
  1523.     growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
  1524.         /* growIconSpace true if window has grow icon or a blank space for one. */
  1525.  
  1526.     wrgn = NewRgn();
  1527.     if (growIconSpace) {
  1528.         rct = window->portRect;
  1529.         rct.left = rct.right  - 15;
  1530.         rct.top  = rct.bottom - 15;
  1531.         RectRgn(wrgn, &rct);
  1532.         UnionRgn(urgn, wrgn, urgn);
  1533.     }
  1534.     for (i = 0; i < 2; ++i) {
  1535.         ctl = (i) ? (*frHndl)->fileState.vScroll : (*frHndl)->fileState.hScroll;
  1536.         if (ctl) {
  1537.             rct = (*ctl)->contrlRect;
  1538.             if (i)
  1539.                 rct.top  -= (*frHndl)->fileState.vScrollIndent;
  1540.             else
  1541.                 rct.left -= (*frHndl)->fileState.hScrollIndent;
  1542.             OffsetRect(&rct, 0, 16384);
  1543.             RectRgn(wrgn, &rct);
  1544.             UnionRgn(urgn, wrgn, urgn);
  1545.         }
  1546.     }
  1547.     DisposeRgn(wrgn);
  1548.  
  1549.     l2g.h = l2g.v = 0;
  1550.     LocalToGlobal(&l2g);
  1551.     OffsetRgn(urgn, l2g.h, l2g.v);
  1552.  
  1553.     SetPort(oldPort);
  1554.     return(urgn);
  1555. }
  1556.  
  1557.  
  1558.  
  1559. /*****************************************************************************/
  1560.  
  1561.  
  1562.  
  1563. void    DoContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
  1564. {
  1565.     FileRecHndl            frHndl;
  1566.     ContentClickProcPtr    proc;
  1567.  
  1568.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1569.  
  1570.     if (!IsDAWindow(window)) {
  1571.         frHndl = (FileRecHndl)GetWRefCon(window);
  1572.         if (frHndl) {
  1573.             proc = (*frHndl)->fileState.contentClickProc;
  1574.             if (proc)
  1575.                 (*proc)(window, event, firstClick);
  1576.         }
  1577.     }
  1578. }
  1579.  
  1580.  
  1581.  
  1582. /*****************************************************************************/
  1583.  
  1584.  
  1585.  
  1586. void    DoDragWindow(WindowPtr window, EventRecord *event, Rect bounds)
  1587. {
  1588.     WindowPtr    oldPort, fwindow;
  1589.     GrafPort    bigPort;
  1590.     WindowPeek    wpeek;
  1591.     FileRecHndl    frHndl;
  1592.     RgnHandle    dragRgn;
  1593.     Point        offset, windOrg;
  1594.     long        wkind;
  1595.  
  1596.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1597.  
  1598.     if (!StillDown()) return;
  1599.  
  1600.     GetPort(&oldPort);
  1601.  
  1602.     OpenPort(&bigPort);
  1603.     CopyRgn(GetGrayRgn(), bigPort.visRgn);
  1604.     bigPort.portRect = (*bigPort.visRgn)->rgnBBox;
  1605.  
  1606.     if (gSystemVersion >= 0x0700) {
  1607.         HMGetBalloonWindow(&fwindow);
  1608.         if (fwindow)
  1609.             DiffRgn(bigPort.visRgn, ((WindowPeek)fwindow)->strucRgn, bigPort.visRgn);
  1610.     }
  1611.  
  1612.     fwindow = (WindowPtr)-1;
  1613.     wkind = kwIsDocument;
  1614.     frHndl = (FileRecHndl)GetWRefCon(window);
  1615.     if (frHndl)
  1616.         if (((WindowPeek)window)->windowKind >= 1000)
  1617.             wkind = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  1618.     fwindow = FrontWindowOfType(wkind, true);
  1619.     for (wpeek = (WindowPeek)FrontWindow(); wpeek; wpeek = wpeek->nextWindow) {
  1620.         if (fwindow == (WindowPtr)wpeek) break;
  1621.         DiffRgn(bigPort.visRgn, wpeek->strucRgn, bigPort.visRgn);
  1622.     }
  1623.  
  1624.     CopyRgn(((WindowPeek)window)->strucRgn, dragRgn = NewRgn());
  1625.     *(long *)&offset = DragGrayRgn(dragRgn, event->where, &bounds, &bounds, noConstraint, nil);
  1626.  
  1627.     DisposeRgn(dragRgn);
  1628.     ClosePort(&bigPort);
  1629.  
  1630.     if ((offset.h != (short)0x8000) || (offset.v != (short)0x8000)) {
  1631.         windOrg.h = window->portRect.left;
  1632.         windOrg.v = window->portRect.top;
  1633.         SetPort(window);
  1634.         LocalToGlobal(&windOrg);
  1635.         MoveWindow(window, windOrg.h + offset.h, windOrg.v + offset.v, false);
  1636.     }
  1637.  
  1638.     SetPort(oldPort);
  1639.  
  1640.     if (!(event->modifiers & cmdKey))
  1641.         CleanSendInFront(window, fwindow);
  1642. }
  1643.  
  1644.  
  1645.  
  1646. /*****************************************************************************/
  1647.  
  1648.  
  1649.  
  1650. void    DoDrawFrame(WindowPtr window, Boolean activate)
  1651. {
  1652.     FileRecHndl            frHndl;
  1653.     WindowPtr            oldPort;
  1654.     Rect                worg;
  1655.     long                attributes;
  1656.     DrawFrameProcPtr    proc;
  1657.  
  1658.     if (window) {
  1659.         frHndl = (FileRecHndl)GetWRefCon(window);
  1660.         if (frHndl) {
  1661.             oldPort = SetFilePort(frHndl);
  1662.             worg    = window->portRect;
  1663.             SetOrigin(0, 0);
  1664.     
  1665.             attributes = (*frHndl)->fileState.attributes;
  1666.             if (attributes & kwGrowIcon)
  1667.                 DoDrawGrowIcon(window, false, false);
  1668.  
  1669.             SetOrigin(0, -16384);
  1670.             DoDrawControls(window, true);
  1671.             SetOrigin(-16384, 0);
  1672.             proc = (*frHndl)->fileState.drawFrameProc;
  1673.             if (proc)
  1674.                 (*proc)(frHndl, window, activate);
  1675.     
  1676.             SetOrigin(worg.left, worg.top);
  1677.             SetPort(oldPort);
  1678.         }
  1679.     }
  1680. }
  1681.  
  1682.  
  1683.  
  1684. /*****************************************************************************/
  1685.  
  1686.  
  1687.  
  1688. OSErr    DoFreeDocument(FileRecHndl frHndl)
  1689. {
  1690.     FreeDocumentProcPtr    proc;
  1691.     OSErr                err;
  1692.  
  1693.     err = noErr;
  1694.     proc = (*frHndl)->fileState.freeDocumentProc;
  1695.     if (proc)
  1696.         err = (*proc)(frHndl);
  1697.     return(err);
  1698. }
  1699.  
  1700.  
  1701.  
  1702. /*****************************************************************************/
  1703.  
  1704.  
  1705.  
  1706. OSErr    DoFreeWindow(FileRecHndl frHndl, WindowPtr window)
  1707. {
  1708.     FreeWindowProcPtr    proc;
  1709.     OSErr                err;
  1710.  
  1711.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1712.  
  1713.     err = noErr;
  1714.     proc = (*frHndl)->fileState.freeWindowProc;
  1715.     if (proc)
  1716.         err = (*proc)(frHndl, window);
  1717.     return(err);
  1718. }
  1719.  
  1720.  
  1721.  
  1722. /*****************************************************************************/
  1723.  
  1724.  
  1725.  
  1726. OSErr    DoImageDocument(FileRecHndl frHndl)
  1727. {
  1728.     ImageProcPtr    proc;
  1729.     OSErr            err;
  1730.  
  1731.     err = noErr;
  1732.     proc = (*frHndl)->fileState.imageProc;
  1733.     if (proc)
  1734.         err = (*proc)(frHndl);
  1735.     return(err);
  1736. }
  1737.  
  1738.  
  1739.  
  1740. /*****************************************************************************/
  1741.  
  1742.  
  1743.  
  1744. OSErr    DoInitContent(FileRecHndl frHndl, WindowPtr window)
  1745. {
  1746.     InitContentProcPtr    proc;
  1747.     OSErr                err;
  1748.  
  1749.     err = noErr;
  1750.     proc = (*frHndl)->fileState.initContentProc;
  1751.     if (proc)
  1752.         err = (*proc)(frHndl, window);
  1753.     return(err);
  1754. }
  1755.  
  1756.  
  1757.  
  1758. /*****************************************************************************/
  1759.  
  1760.  
  1761.  
  1762. Boolean    DoKeyDown(EventRecord *event)
  1763. {
  1764.     char                key;
  1765.     WindowPtr            window, fwindow;
  1766.     FileRecHndl            frHndl;
  1767.     ContentKeyProcPtr    proc;
  1768.     Boolean                passThrough;
  1769.     short                menuID, menuItem, menuItem2, charsUsed;
  1770.     long                menuVal, attr, wkind;
  1771.     Str32                str;
  1772.     OSType                sftype;
  1773.     OSErr                err;
  1774.     DoMenuItemProcPtr    mproc, mp;
  1775.  
  1776.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1777.  
  1778.     key = event->message & charCodeMask;
  1779.     if (event->modifiers & cmdKey) {        /* If command key down... */
  1780.         if (event->what == keyDown) {
  1781.             DoAdjustMenus();                /* Prepare menus properly. */
  1782.             menuVal   = MenuKey(key);
  1783.             menuID    = HiWord(menuVal);
  1784.             menuItem  = LoWord(menuVal);
  1785.             menuItem2 = MapMItem(menuID, menuItem);
  1786.             if (menuID) {
  1787.                 mproc = DoMenuItem;
  1788.                 if (IsAppWindow(window = FrontWindow())) {
  1789.                     mp = (*(FileRecHndl)GetWRefCon(window))->fileState.doMenuItemProc;
  1790.                     if (mp)
  1791.                         mproc = mp;
  1792.                 }
  1793.                 if (!(*mproc)(window, menuID, menuItem2)) {
  1794.                     GetIndString(str, menuID, menuItem);
  1795.                     if (str[0]) {
  1796.                         p2dec(str, &charsUsed);
  1797.                         if (str[0] > charsUsed + 2) {
  1798.                             if (str[charsUsed + 2] == '\'') {
  1799.                                 BlockMove(str + charsUsed + 3, (Ptr)&sftype, sizeof(OSType));
  1800.                                 window = GetNextWindow(nil, sftype);
  1801.                                 if (window) {
  1802.                                     frHndl = (FileRecHndl)GetWRefCon(window);
  1803.                                     attr   = (*frHndl)->fileState.attributes;
  1804.                                     if (attr & kwHideOnClose) {
  1805.                                         if (!((WindowPeek)window)->visible)
  1806.                                             ShowHide(window, true);
  1807.                                         wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1808.                                         if (!(fwindow = FrontWindowOfType(wkind, false)))
  1809.                                             fwindow = (WindowPtr)-1;
  1810.                                         CleanSendInFront(window, fwindow);
  1811.                                     }
  1812.                                     else window = nil;
  1813.                                 }
  1814.                                 if (!window) {
  1815.                                     DoSetResCursor(watchCursor);
  1816.                                     err = NewDocumentWindow(&frHndl, sftype, true);
  1817.                                     if (!err) {
  1818.                                         if (frHndl) {
  1819.                                             window = (*frHndl)->fileState.window;
  1820.                                             attr   = (*frHndl)->fileState.attributes;
  1821.                                             if (!((WindowPeek)window)->visible)
  1822.                                                 ShowHide(window, true);
  1823.                                             wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1824.                                             if (!(fwindow = FrontWindowOfType(wkind, false)))
  1825.                                                 fwindow = (WindowPtr)-1;
  1826.                                             CleanSendInFront(window, fwindow);
  1827.                                         }
  1828.                                     }
  1829.                                     else {
  1830.                                         gDialogErr = err;
  1831.                                         NewDocumentWindow(nil, 'ERR#', false);
  1832.                                     }
  1833.                                 }
  1834.                             }
  1835.                         }
  1836.                     }
  1837.                 }
  1838.                 HiliteMenu(0);        /* Unhighlight what MenuKey hilited. */
  1839.                 DoSetCursor(nil);
  1840.                 return(false);
  1841.             }
  1842.         }
  1843.         else return(false);
  1844.     }
  1845.  
  1846.     for (window = nil; (window = GetNextWindow(window, 0)) != nil;) {
  1847.         if (!((WindowPeek)window)->visible) continue;
  1848.         if (((WindowPeek)window)->windowKind >= 1000) {
  1849.             frHndl = (FileRecHndl)GetWRefCon(window);
  1850.             if (frHndl) {
  1851.                 proc = (*frHndl)->fileState.contentKeyProc;
  1852.                 if (proc) {
  1853.                     passThrough = false;
  1854.                     if ((*proc)(window, event, &passThrough)) return(true);
  1855.                     if (!passThrough) break;
  1856.                 }
  1857.             }
  1858.         }
  1859.     }
  1860.  
  1861.     return(false);
  1862. }
  1863.  
  1864.  
  1865.  
  1866. /*****************************************************************************/
  1867.  
  1868.  
  1869.  
  1870. void    DoMouseDown(EventRecord *event)
  1871. {
  1872.     WindowPtr            window, fwindow, dlog, ww;
  1873.     FileRecHndl            frHndl;
  1874.     Rect                contentRct, old, growLimits, tearRect;
  1875.     Point                pt;
  1876.     short                part, menuID, menuItem, menuItem2, charsUsed;
  1877.     long                menuVal, size, wkind, attr;
  1878.     Str63                str;
  1879.     OSType                sftype;
  1880.     OSErr                err;
  1881.     DoMenuItemProcPtr    mproc, mp;
  1882.  
  1883.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1884.  
  1885.     part = FindWindow(event->where, &window);
  1886.  
  1887.     frHndl = nil;
  1888.     if (window)
  1889.         if (((WindowPeek)window)->windowKind >= 1000)
  1890.             frHndl = (FileRecHndl)GetWRefCon(window);
  1891.  
  1892.     if (part != inContent)
  1893.         DoSetCursor(&qd.arrow);
  1894.  
  1895.     dlog = FrontWindowOfType(kwIsModalDialog, true);
  1896.     if ((dlog) && (window != dlog)) {
  1897.         if (part != inMenuBar) {
  1898.             SysBeep(1);
  1899.             return;
  1900.         }
  1901.     }
  1902.  
  1903.     switch(part) {
  1904.  
  1905.         case inContent:
  1906.  
  1907.             if (!IsAppWindow(window)) {
  1908.                 if (window != FrontWindow()) {
  1909.                     SelectWindow(window);
  1910.                     HiliteWindows();
  1911.                 }
  1912.                 break;
  1913.             }
  1914.  
  1915.             wkind   = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  1916.             fwindow = FrontWindowOfType(wkind, true);
  1917.                 /* fwindow guaranteed, since worst case we find ourself. */
  1918.  
  1919.             if (window == fwindow) {
  1920.                 DoContentClick(window, event, false);
  1921.                 break;
  1922.             }        /* The window is the frontmost of this type, so handle the click. */
  1923.  
  1924.             CleanSendInFront(window, fwindow);
  1925.  
  1926.             if ((*frHndl)->fileState.attributes & kwDoFirstClick) {
  1927.                 DoUpdate(window);
  1928.                 contentRct = GetWindowContentRect(window);
  1929.                 if (PtInRect(event->where, &contentRct))
  1930.                     DoContentClick(window, event, true);
  1931.             }
  1932.             break;
  1933.  
  1934.         case inDrag:
  1935.             DoDragWindow(window, event, qd.screenBits.bounds);
  1936.             break;        /* Pass screenBits.bounds to get all gDevices. */
  1937.  
  1938.         case inGoAway:
  1939.             if (TrackGoAway(window, event->where))
  1940.                 DisposeOneWindow(window, kClose);
  1941.             break;
  1942.  
  1943.         case inGrow:
  1944.             old = GetWindowContentRect(window);
  1945.             growLimits = (*frHndl)->fileState.windowSizeBounds;
  1946.             ++growLimits.right;
  1947.             ++growLimits.bottom;
  1948.             size = GrowWindow(window, event->where, &growLimits);
  1949.             if (size) {
  1950.                 pt = *(Point *)&size;
  1951.                 SizeWindow(window, pt.h, pt.v, true);
  1952.                 DoResizeWindow(window, old.right - old.left, old.bottom - old.top);
  1953.             }
  1954.             break;
  1955.  
  1956.         case inMenuBar:        /* Process mouse menu command (if any). */
  1957.             DoAdjustMenus();
  1958.             DoSetCursor(&qd.arrow);
  1959.             menuVal  = MenuSelect(event->where);
  1960.             menuID   = HiWord(menuVal);
  1961.             menuItem = LoWord(menuVal);
  1962.             if (menuItem == -1)
  1963.                 menuItem = CountMItems(GetMenuHandle(menuID));
  1964.             menuItem2 = MapMItem(menuID, menuItem);
  1965.             mproc = DoMenuItem;
  1966.             if (IsAppWindow(window = FrontWindow())) {
  1967.                 mp = (*(FileRecHndl)GetWRefCon(window))->fileState.doMenuItemProc;
  1968.                 if (mp)
  1969.                     mproc = mp;
  1970.             }
  1971.             if (!(*mproc)(window, menuID, menuItem2)) {
  1972.                 GetIndString(str, menuID, menuItem);
  1973.                 if (str[0]) {
  1974.                     p2dec(str, &charsUsed);
  1975.                     if (str[0] > charsUsed + 2) {
  1976.                         if (str[charsUsed + 2] == '\'') {
  1977.                             BlockMove(str + charsUsed + 3, (Ptr)&sftype, sizeof(OSType));
  1978.                             window = GetNextWindow(nil, sftype);
  1979.                             if (window) {
  1980.                                 frHndl = (FileRecHndl)GetWRefCon(window);
  1981.                                 attr   = (*frHndl)->fileState.attributes;
  1982.                                 if (attr & kwHideOnClose) {
  1983.                                     if (menuItem2 == -1) {
  1984.                                         GetMenuItemText(GetMenuHandle(menuID), menuItem, str);
  1985.                                         BlockMove(str + 1, &tearRect, sizeof(Rect));
  1986.                                         MoveWindow(window, tearRect.left, tearRect.top, false);
  1987.                                     }
  1988.                                     if (!((WindowPeek)window)->visible)
  1989.                                         ShowHide(window, true);
  1990.                                     wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1991.                                     if (!(fwindow = FrontWindowOfType(wkind, false)))
  1992.                                         fwindow = (WindowPtr)-1;
  1993.                                     CleanSendInFront(window, fwindow);
  1994.                                 }
  1995.                                 else window = nil;
  1996.                             }
  1997.                             if (!window) {
  1998.                                 DoSetResCursor(watchCursor);
  1999.                                 err = NewDocumentWindow(&frHndl, sftype, true);
  2000.                                 if (!err) {
  2001.                                     if (frHndl) {
  2002.                                         window = (*frHndl)->fileState.window;
  2003.                                         attr   = (*frHndl)->fileState.attributes;
  2004.                                         if (!((WindowPeek)window)->visible)
  2005.                                             ShowHide(window, true);
  2006.                                         wkind = (attr & (kwIsPalette | kwIsModalDialog));
  2007.                                         if (!(fwindow = FrontWindowOfType(wkind, false)))
  2008.                                             fwindow = (WindowPtr)-1;
  2009.                                         CleanSendInFront(window, fwindow);
  2010.                                     }
  2011.                                 }
  2012.                                 else {
  2013.                                     gDialogErr = err;
  2014.                                     NewDocumentWindow(nil, 'ERR#', false);
  2015.                                 }
  2016.                             }
  2017.                         }
  2018.                     }
  2019.                 }
  2020.             }
  2021.             HiliteMenu(0);        /* Unhighlight what MenuSelect hilited. */
  2022.             break;
  2023.  
  2024.         case inSysWindow:    /* Let the system handle the mouseDown. */
  2025.             SystemClick(event, window);
  2026.             for (ww = FrontWindow(); ww; ww = (WindowPtr)(((WindowPeek)ww)->nextWindow))
  2027.                 if (ww == window) break;
  2028.                     /* We have to go find out if the window was closed ourselves.  Silly, huh. */
  2029.             if (!ww) WindowGoneFixup(window);
  2030.             break;
  2031.  
  2032.         case inZoomIn:
  2033.         case inZoomOut:
  2034.             DoZoomWindow(window, event, part);
  2035.             break;
  2036.  
  2037.     }
  2038. }
  2039.  
  2040.  
  2041.  
  2042. /*****************************************************************************/
  2043.  
  2044.  
  2045.  
  2046. /* This function converts a menu item hard-id (one returned by the toolbox) to a
  2047. ** soft-id (defined in the 'STR#' resource associated with the menu.  If there is
  2048. ** a 'STR#' resource defined with the same id as the menu, it is assumed to be
  2049. ** for the purpose of converting hard-id values to soft-id values. */
  2050.  
  2051. short    MapMItem(short menuID, short menuItem)
  2052. {
  2053.     Str32    str;
  2054.  
  2055.     if (menuID == 128)
  2056.         return(menuItem);
  2057.  
  2058.     GetIndString(str, menuID, menuItem);
  2059.     if (str[0])
  2060.         menuItem = p2dec(str, nil);
  2061.  
  2062.     return(menuItem);
  2063. }
  2064.  
  2065.  
  2066.  
  2067. /*****************************************************************************/
  2068.  
  2069.  
  2070.  
  2071. /* This function is the logical reverse of MapMItem(). */
  2072.  
  2073. short    UnmapMItem(short menuID, short menuItem)
  2074. {
  2075.     Str32    str;
  2076.     short    i, j;
  2077.  
  2078.     if (menuID == 128)                   return(menuItem);
  2079.     if (!Get1Resource('STR#', menuID)) return(menuItem);
  2080.         /* No such table, so don't convert it. */
  2081.  
  2082.     if (menuItem) {
  2083.         for (i = 1;; ++i) {
  2084.             GetIndString(str, menuID, i);
  2085.             if (!str[0]) return(32767);        /* No such entry found.  Return something invalid. */
  2086.             j = p2dec(str, nil);
  2087.             if (menuItem == j) return(i);
  2088.         }
  2089.     }
  2090.  
  2091.     return(menuItem);
  2092. }
  2093.  
  2094.  
  2095.  
  2096. /*****************************************************************************/
  2097.  
  2098.  
  2099.  
  2100. OSErr    DoReadDocument(FileRecHndl frHndl)
  2101. {
  2102.     ReadDocumentProcPtr    proc;
  2103.     OSErr                err;
  2104.  
  2105.     err = noErr;
  2106.     proc = (*frHndl)->fileState.readDocumentProc;
  2107.     if (proc)
  2108.         err = (*proc)(frHndl);
  2109.     return(err);
  2110. }
  2111.  
  2112.  
  2113.  
  2114. /*****************************************************************************/
  2115.  
  2116.  
  2117.  
  2118. OSErr    DoReadDocumentHeader(FileRecHndl frHndl)
  2119. {
  2120.     ReadDocumentHeaderProcPtr    proc;
  2121.     OSErr                        err;
  2122.  
  2123.     err = noErr;
  2124.     if ((*frHndl)->fileState.refNum) {
  2125.         proc = (*frHndl)->fileState.readDocumentHeaderProc;
  2126.         if (proc)
  2127.             err = (*proc)(frHndl);
  2128.     }
  2129.     return(err);
  2130. }
  2131.  
  2132.  
  2133.  
  2134. /*****************************************************************************/
  2135.  
  2136.  
  2137.  
  2138. OSErr    DefaultReadDocumentHeader(FileRecHndl frHndl)
  2139. {
  2140.     short    refNum, vers, resAlreadyOpen, oldRes;
  2141.     OSErr    err;
  2142.     char    hstate;
  2143.     Ptr        ptr1, ptr2;
  2144.     long    count, attr;
  2145.     OSType    sftype;
  2146.     Handle    hndl;
  2147.  
  2148.     err = SetFPos(refNum = (*frHndl)->fileState.refNum, fsFromStart, 0);
  2149.     if (err) return(err);
  2150.  
  2151.     attr   = (*frHndl)->fileState.attributes;
  2152.     sftype = (*frHndl)->fileState.sfType;
  2153.  
  2154.     if (attr & kwDefaultDocHeader) {
  2155.         if (sftype != MovieFileType) {
  2156.             if (attr & kwHeaderIsResource) {
  2157.                 resAlreadyOpen = (*frHndl)->fileState.resRefNum;
  2158.                 UseDocResFile(frHndl, &oldRes, fsRdWrPerm);
  2159.                 hndl = Get1Resource('DFDH', 128);
  2160.                 err  = ResError();
  2161.                 if (!err)
  2162.                     if (!hndl)
  2163.                         err = resNotFound;
  2164.                 if (!err) {
  2165.                     ptr1   = (Ptr)&((*frHndl)->d.doc);
  2166.                     ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2167.                     count  = (long)ptr2 - (long)ptr1;
  2168.                     BlockMove(*hndl, ptr1, count);
  2169.                 }
  2170.                 if (hndl)
  2171.                     ReleaseResource(hndl);
  2172.                 if (!resAlreadyOpen)
  2173.                     CloseDocResFile(frHndl);
  2174.                 UseResFile(oldRes);
  2175.             }
  2176.             else {
  2177.                 if (!err) {        /* Read header info from file. */
  2178.                     hstate = HGetState((Handle)frHndl);
  2179.                     HLock((Handle)frHndl);
  2180.                     ptr1   = (Ptr)&((*frHndl)->d.doc);
  2181.                     ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2182.                     count  = (long)ptr2 - (long)ptr1;
  2183.                     err    = FSRead(refNum, &count, ptr1);
  2184.                     HSetState((Handle)frHndl, hstate);
  2185.                 }
  2186.             }
  2187.             if (!err) {
  2188.                 vers = (*frHndl)->d.doc.fhInfo.version;
  2189.                 if ((vers < gMinVersion) || (vers > gMaxVersion))
  2190.                     err = kWrongVersion;
  2191.             }
  2192.         }
  2193.     }
  2194.  
  2195.     return(err);
  2196. }
  2197.  
  2198.  
  2199.  
  2200. /*****************************************************************************/
  2201.  
  2202.  
  2203.  
  2204. OSErr    DoWriteDocument(FileRecHndl frHndl)
  2205. {
  2206.     WriteDocumentProcPtr    proc;
  2207.     OSErr                    err;
  2208.  
  2209.     err = noErr;
  2210.     proc = (*frHndl)->fileState.writeDocumentProc;
  2211.     if (proc)
  2212.         err = (*proc)(frHndl);
  2213.     return(err);
  2214. }
  2215.  
  2216.  
  2217.  
  2218. /*****************************************************************************/
  2219.  
  2220.  
  2221.  
  2222. OSErr    DoWriteDocumentHeader(FileRecHndl frHndl)
  2223. {
  2224.     WriteDocumentHeaderProcPtr    proc;
  2225.     OSErr                        err;
  2226.  
  2227.     err = noErr;
  2228.     if ((*frHndl)->fileState.refNum) {
  2229.         proc = (*frHndl)->fileState.writeDocumentHeaderProc;
  2230.         if (proc)
  2231.             err = (*proc)(frHndl);
  2232.     }
  2233.     return(err);
  2234. }
  2235.  
  2236.  
  2237.  
  2238. /*****************************************************************************/
  2239.  
  2240.  
  2241.  
  2242. OSErr    DefaultWriteDocumentHeader(FileRecHndl frHndl)
  2243. {
  2244.     short        refNum, resAlreadyOpen, oldRes;
  2245.     OSErr        err;
  2246.     WindowPtr    window;
  2247.     char        hstate;
  2248.     Ptr            ptr1, ptr2;
  2249.     long        count, attr;
  2250.     OSType        sftype;
  2251.     Handle        hndl;
  2252.  
  2253.     err = SetFPos(refNum = (*frHndl)->fileState.refNum, fsFromStart, 0);
  2254.     if (err) return(err);
  2255.  
  2256.     attr   = (*frHndl)->fileState.attributes;
  2257.     sftype = (*frHndl)->fileState.sfType;
  2258.  
  2259.     if (attr & kwDefaultDocHeader) {
  2260.         if (sftype != MovieFileType) {
  2261.             window = (*frHndl)->fileState.window;
  2262.             if (window) {
  2263.                 if (!(*frHndl)->fileState.readOnly) {
  2264.                     (*frHndl)->d.doc.fhInfo.structureRect = GetWindowStructureRect(window);
  2265.                     (*frHndl)->d.doc.fhInfo.contentRect   = GetWindowContentRect(window);
  2266.                     (*frHndl)->d.doc.fhInfo.stdState      = mDerefWStateData(window)->stdState;
  2267.                     if (((WindowPeek)window)->spareFlag)
  2268.                         (*frHndl)->d.doc.fhInfo.userState = mDerefWStateData(window)->userState;
  2269.                 }
  2270.             }
  2271.             else SetRect(&(*frHndl)->d.doc.fhInfo.structureRect, 0, 0, 0, 0);
  2272.             if (attr & kwHeaderIsResource) {
  2273.                 resAlreadyOpen = (*frHndl)->fileState.resRefNum;
  2274.                 UseDocResFile(frHndl, &oldRes, fsRdWrPerm);
  2275.                 ptr1   = (Ptr)&((*frHndl)->d.doc);
  2276.                 ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2277.                 count  = (long)ptr2 - (long)ptr1;
  2278.                 hndl = Get1Resource('DFDH', 128);
  2279.                 if (hndl) {
  2280.                     RemoveResource(hndl);
  2281.                     DisposeHandle(hndl);
  2282.                 }
  2283.                 hndl = NewHandle(count);
  2284.                 if (hndl) {
  2285.                     ptr1 = (Ptr)&((*frHndl)->d.doc);
  2286.                     BlockMove(ptr1, *hndl, count);
  2287.                     AddResource(hndl, 'DFDH', 128, nil);
  2288.                     ChangedResource(hndl);
  2289.                     WriteResource(hndl);
  2290.                     UpdateResFile(CurResFile());
  2291.                     DetachResource(hndl);
  2292.                     DisposeHandle(hndl);
  2293.                 }
  2294.                 else err = memFullErr;
  2295.                 if (!resAlreadyOpen)
  2296.                     CloseDocResFile(frHndl);
  2297.                 UseResFile(oldRes);
  2298.             }
  2299.             else {
  2300.                 hstate = HGetState((Handle)frHndl);
  2301.                 HLock((Handle)frHndl);
  2302.                 ptr1   = (Ptr)&((*frHndl)->d.doc);
  2303.                 ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2304.                 count  = (long)ptr2 - (long)ptr1;
  2305.                 err    = FSWrite(refNum, &count, ptr1);
  2306.                 HSetState((Handle)frHndl, hstate);
  2307.             }
  2308.         }
  2309.     }
  2310.  
  2311.     return(err);
  2312. }
  2313.  
  2314.  
  2315.  
  2316. /*****************************************************************************/
  2317.  
  2318.  
  2319.  
  2320. void    DoResizeContent(WindowPtr window, short oldh, short oldv)
  2321. {
  2322.     FileRecHndl                frHndl;
  2323.     ResizeContentProcPtr    proc;
  2324.  
  2325.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2326.  
  2327.     if (IsAppWindow(window)) {
  2328.         frHndl = (FileRecHndl)GetWRefCon(window);
  2329.         if (frHndl) {
  2330.             proc = (*frHndl)->fileState.resizeContentProc;
  2331.             if (proc)
  2332.                 (*proc)(window, oldh, oldv);
  2333.         }
  2334.     }
  2335. }
  2336.  
  2337.  
  2338.  
  2339. /*****************************************************************************/
  2340.  
  2341.  
  2342.  
  2343. void    DoScrollFrame(WindowPtr window, long dh, long dv)
  2344. {
  2345.     FileRecHndl            frHndl;
  2346.     ScrollFrameProcPtr    proc;
  2347.  
  2348.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2349.  
  2350.     if (IsAppWindow(window)) {
  2351.         frHndl = (FileRecHndl)GetWRefCon(window);
  2352.         if (frHndl) {
  2353.             proc = (*frHndl)->fileState.scrollFrameProc;
  2354.             if (proc)
  2355.                 (*proc)(frHndl, window, dh, dv);
  2356.         }
  2357.     }
  2358. }
  2359.  
  2360.  
  2361.  
  2362. /*****************************************************************************/
  2363.  
  2364.  
  2365.  
  2366. void    DoUndoFixup(FileRecHndl frHndl, Point contOrg, Boolean afterUndo)
  2367. {
  2368.     UndoFixupProcPtr    proc;
  2369.  
  2370.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2371.  
  2372.     proc = (*frHndl)->fileState.undoFixupProc;
  2373.     if (proc)
  2374.         (*proc)(frHndl, contOrg, afterUndo);
  2375. }
  2376.  
  2377.  
  2378.  
  2379. /*****************************************************************************/
  2380. /*****************************************************************************/
  2381.  
  2382.  
  2383.  
  2384. /* Open a window where it was stored at.  This would be simple, except for the
  2385. ** complication that the user may be opening the document on a different Mac
  2386. ** that doesn't have the same monitor configuration.  Due to this, we need to
  2387. ** make sure that the window doesn't open completely out of view. */
  2388.  
  2389. static Rect    OldLocWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  2390. {
  2391.     FileRecHndl    frHndl;
  2392.     RgnHandle    rgn;
  2393.     Rect        rct, bbox, srct, crct;
  2394.     short        dh, dv, h, v;
  2395.     long        attributes;
  2396.  
  2397.     frHndl     = (FileRecHndl)GetWRefCon(window);
  2398.     attributes = (*frHndl)->fileState.attributes;
  2399.  
  2400.     srct = (*frHndl)->d.doc.fhInfo.structureRect;
  2401.     crct = (*frHndl)->d.doc.fhInfo.contentRect;
  2402.     if (EmptyRect(&srct)) {
  2403.         if (!gOldLocProc) return(window->portRect);
  2404.         return((*gOldLocProc)(window, relatedWindow, sizeInfo));
  2405.     }
  2406.  
  2407.     rct = srct;
  2408.     rct.bottom = crct.top;
  2409.  
  2410.     RectRgn(rgn = NewRgn(), &rct);
  2411.     SectRgn(rgn, GetGrayRgn(), rgn);
  2412.     bbox = (*rgn)->rgnBBox;
  2413.     DisposeRgn(rgn);
  2414.  
  2415.     if (EqualRect(&rct, &bbox)) {
  2416.         rct = (*frHndl)->d.doc.fhInfo.contentRect;
  2417.         SizeWindow(window, rct.right - rct.left, rct.bottom - rct.top, false);
  2418.         MoveWindow(window, rct.left, rct.top, false);
  2419.         mDerefWStateData(window)->stdState  = (*frHndl)->d.doc.fhInfo.stdState;
  2420.         if (((WindowPeek)window)->spareFlag)
  2421.             mDerefWStateData(window)->userState = (*frHndl)->d.doc.fhInfo.userState;
  2422.         return(rct);
  2423.     }
  2424.  
  2425.     rct = srct;
  2426.     if (!(dh = bbox.left - rct.left))
  2427.         dh = bbox.right  - rct.right;
  2428.     if (!(dv = bbox.top  - rct.top))
  2429.         dv = bbox.bottom - rct.bottom;
  2430.     OffsetRect(&rct, dh, dv);
  2431.  
  2432.     RectRgn(rgn = NewRgn(), &rct);
  2433.     SectRgn(rgn, GetGrayRgn(), rgn);
  2434.     bbox = (*rgn)->rgnBBox;
  2435.     DisposeRgn(rgn);
  2436.  
  2437.     if (EqualRect(&rct, &bbox)) {
  2438.         h = crct.right  - crct.left;
  2439.         v = crct.bottom - crct.top;
  2440.         SetRect(&sizeInfo, h, v, h, v);
  2441.             /* Force window big as possible for this screen and data size. */
  2442.     }
  2443.  
  2444.     if (!gOldLocProc) return(window->portRect);
  2445.     return((*gOldLocProc)(window, relatedWindow, sizeInfo));
  2446. }
  2447.  
  2448.  
  2449.  
  2450. /*****************************************************************************/
  2451.  
  2452.  
  2453.  
  2454. void    CleanSendBehind(WindowPtr window, WindowPtr afterWindow)
  2455. {
  2456.     WindowPtr    oldPort;
  2457.     Point        offset;
  2458.     RgnHandle    contRgn, keepContRgn, visRgn;
  2459.  
  2460.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2461.  
  2462.     if (afterWindow == (WindowPtr)-1) {
  2463.         BringToFront(window);
  2464.         HiliteWindows();
  2465.         return;
  2466.     }
  2467.  
  2468.     GetPort(&oldPort);
  2469.     SetPort(window);
  2470.     offset.h = offset.v = 0;
  2471.     LocalToGlobal(&offset);
  2472.     SetPort(oldPort);
  2473.  
  2474.     CopyRgn(contRgn = ((WindowPeek)window)->contRgn, keepContRgn = NewRgn());
  2475.     OffsetRgn(visRgn = window->visRgn, offset.h, offset.v);
  2476.     DiffRgn(contRgn, visRgn, contRgn);
  2477.     OffsetRgn(visRgn, -offset.h, -offset.v);
  2478.         /* Don't allow PaintOne to touch the part of the window already visible. */
  2479.  
  2480.     SendBehind(window, afterWindow);
  2481.         /* Do the SendBehind.  Since the content region is way off the
  2482.         ** screen(s), no erasing of the content of the window will occur. */
  2483.  
  2484.     CopyRgn(keepContRgn, contRgn);
  2485.     DisposeRgn(keepContRgn);
  2486.  
  2487.     CalcVis((WindowPeek)window);
  2488.         /* One negative to the content region games is that the visRgn gets
  2489.         ** calculated incorrectly when SendBehind() is called.  The call to
  2490.         ** CalcVis() fixes this problem. */
  2491.  
  2492.     HiliteWindows();
  2493. }
  2494.  
  2495.  
  2496.  
  2497. /*****************************************************************************/
  2498.  
  2499.  
  2500.  
  2501. void    CleanSendInFront(WindowPtr window, WindowPtr beforeWindow)
  2502. {
  2503.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2504.  
  2505.     beforeWindow = GetPreviousWindow(beforeWindow);
  2506.     while (beforeWindow) {
  2507.         if (((WindowPeek)beforeWindow)->visible) break;
  2508.         beforeWindow = GetPreviousWindow(beforeWindow);
  2509.     }
  2510.  
  2511.     if (beforeWindow)
  2512.         CleanSendBehind(window, beforeWindow);
  2513. }
  2514.  
  2515.  
  2516.  
  2517. /*****************************************************************************/
  2518.  
  2519.  
  2520.  
  2521. void    HiliteWindows(void)
  2522. {
  2523.     WindowPtr    window, ww;
  2524.     FileRecHndl    frHndl, ff;
  2525.     long        thisKind, lastKind;
  2526.     Boolean        haveModal;
  2527.     short        hilited;
  2528.  
  2529.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2530.  
  2531.     lastKind = -1;            /* No such kind. */
  2532.  
  2533.     haveModal = false;
  2534.     for (window = FrontWindow(); window; window = (WindowPtr)(((WindowPeek)window)->nextWindow)) {
  2535.  
  2536.         if (!((WindowPeek)window)->visible)          continue;
  2537.         if (((WindowPeek)window)->windowKind < 1000) continue;
  2538.  
  2539.         thisKind = kwIsDocument;
  2540.         if (IsAppWindow(window)) {
  2541.             frHndl   = (FileRecHndl)GetWRefCon(window);
  2542.             thisKind = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  2543.         }
  2544.  
  2545.         if (gInBackground)
  2546.             lastKind = thisKind;
  2547.                 /* If application moved to background, we want to turn all hilighting off
  2548.                 ** for all windows.  This is accomplished by pretending that the kind of
  2549.                 ** the current window is the same as the kind of the last window. */
  2550.  
  2551.         if (haveModal)
  2552.             lastKind = thisKind;
  2553.                 /* If we have a modal dialog in front, then turn off the hilighting for
  2554.                 ** all the other windows. */
  2555.  
  2556.         if (thisKind != lastKind) {
  2557.             for (ww = window; (ww = (WindowPtr)(((WindowPeek)ww)->nextWindow)) != nil;) {
  2558.                 if (!((WindowPeek)ww)->visible) continue;
  2559.                 if ((IsAppWindow(ww)) || (IsDAWindow(window))) {
  2560.                     ff = (FileRecHndl)GetWRefCon(ww);
  2561.                     if (thisKind == ((*ff)->fileState.attributes & (kwIsPalette | kwIsModalDialog))) {
  2562.                         hilited = ((WindowPeek)ww)->hilited & 0x01;
  2563.                         if (thisKind == kwIsPalette) {
  2564.                             if (!hilited) {
  2565.                                 HiliteWindow(ww, true);
  2566.                                 DoActivate(ww);
  2567.                             }
  2568.                         }
  2569.                         else {
  2570.                             if (hilited) {
  2571.                                 HiliteWindow(ww, false);
  2572.                                 DoActivate(ww);
  2573.                             }
  2574.                         }
  2575.                     }
  2576.                     else break;
  2577.                 }
  2578.             }
  2579.             hilited = ((WindowPeek)window)->hilited & 0x01;
  2580.             if (!hilited) {
  2581.                 HiliteWindow(window, true);
  2582.                 DoActivate(window);
  2583.             }
  2584.             lastKind = thisKind;
  2585.         }
  2586.         else {
  2587.             hilited = ((WindowPeek)window)->hilited & 0x01;
  2588.             if (hilited) {
  2589.                 HiliteWindow(window, false);
  2590.                 DoActivate(window);
  2591.             }
  2592.         }
  2593.  
  2594.         if (thisKind == kwIsModalDialog)
  2595.             haveModal = true;
  2596.     }
  2597. }
  2598.  
  2599.  
  2600.  
  2601. /*****************************************************************************/
  2602.  
  2603.  
  2604.  
  2605. void    UnhiliteWindows(void)
  2606. {
  2607.     WindowPtr    window;
  2608.     short        hilited;
  2609.  
  2610.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2611.  
  2612.     for (window = nil; (window = GetNextWindow(window, 0)) != nil;) {
  2613.         if (!((WindowPeek)window)->visible) continue;
  2614.         if (IsAppWindow(window))
  2615.             if (((WindowPeek)window)->windowKind <= dialogKind)
  2616.                 continue;
  2617.         hilited = ((WindowPeek)window)->hilited & 0x01;
  2618.         if (hilited) {
  2619.             HiliteWindow(window, false);
  2620.             DoActivate(window);
  2621.         }
  2622.     }
  2623. }
  2624.  
  2625.  
  2626.  
  2627. /*****************************************************************************/
  2628.  
  2629.  
  2630.  
  2631. /* This is called when an update event is received for a window.  First, the
  2632. ** updateRgn is separated into two parts.  Part 1 holds the window frame area,
  2633. ** if any.  This is the area that might hold the scrollbars, grow icon, and
  2634. ** any other application-specific frame parts.  This is drawn first.  Once
  2635. ** this is done, the remainder of the updateRgn is drawn.  This allows us to
  2636. ** handle all of the frame clipping without using the clipRgn.  By freeing up
  2637. ** the clipRgn, we allow the application to use it without having to share. */
  2638.  
  2639. void    DoUpdate(WindowPtr window)
  2640. {
  2641.     RgnHandle    contPart, framePart;
  2642.     Point        contOrg;
  2643.     FileRecHndl    frHndl;
  2644.  
  2645.     SetPort(window);
  2646.  
  2647.     if (IsAppWindow(window)) {
  2648.  
  2649.         DoUpdateSeparate(window, &contPart, &framePart);
  2650.  
  2651.         if (framePart) {        /* Update the document frame, if any. */
  2652.             CopyRgn(framePart, ((WindowPeek)window)->updateRgn);
  2653.             DisposeRgn(framePart);
  2654.             ++gBeginUpdateNested;
  2655.             BeginUpdate(window);
  2656.             DoDrawFrame(window, false);
  2657.             if (gBeginUpdateNested) {
  2658.                 EndUpdate(window);
  2659.                 --gBeginUpdateNested;
  2660.             }
  2661.         }
  2662.         if (contPart) {            /* Update the rest of the content. */
  2663.             CopyRgn(contPart, ((WindowPeek)window)->updateRgn);
  2664.             DisposeRgn(contPart);
  2665.             ++gBeginUpdateNested;
  2666.             BeginUpdate(window);
  2667.             GetContentOrigin(window, &contOrg);
  2668.             SetOrigin(contOrg.h, contOrg.v);
  2669.             frHndl = (FileRecHndl)GetWRefCon(window);
  2670.             DoImageDocument(frHndl);
  2671.             SetOrigin(0, 0);
  2672.             if (gBeginUpdateNested) {
  2673.                 EndUpdate(window);
  2674.                 --gBeginUpdateNested;
  2675.             }
  2676.         }
  2677.     }
  2678. }
  2679.  
  2680.  
  2681.  
  2682. /*****************************************************************************/
  2683.  
  2684.  
  2685.  
  2686. void    DoSetCursor(Cursor *cursor)
  2687. {
  2688.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2689.  
  2690.     if (cursor)
  2691.         SetCursor(cursor);
  2692.  
  2693.     if (!cursor)
  2694.         DoCursor();
  2695. }
  2696.  
  2697.  
  2698.  
  2699. /*****************************************************************************/
  2700.  
  2701.  
  2702.  
  2703. CursPtr    DoSetResCursor(short crsrID)
  2704. {
  2705.     CursHandle    crsr;
  2706.  
  2707.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2708.  
  2709.     crsr = GetCursor(crsrID);
  2710.     if (crsr) {
  2711.         gCursor = **crsr;
  2712.         DoSetCursor(&gCursor);
  2713.         return(&gCursor);
  2714.     }
  2715.  
  2716.     SetCursor(&qd.arrow);
  2717.     return(&qd.arrow);
  2718. }
  2719.  
  2720.  
  2721.  
  2722. /*****************************************************************************/
  2723.  
  2724.  
  2725.  
  2726. void    DoWindowCursor(void)
  2727. {
  2728.     WindowPeek            wpeek;
  2729.     WindowPtr            window;
  2730.     Point                mouseLoc;
  2731.     FileRecHndl            frHndl;
  2732.     RgnHandle            srgn;
  2733.     WindowCursorProcPtr    proc;
  2734.  
  2735.     if (gInBackground) return;
  2736.         /* Don't change cursors if we aren't the front application. */
  2737.  
  2738.     if (!gCursorRgn)
  2739.         gCursorRgn = NewRgn();
  2740.  
  2741.     mouseLoc = GetGlobalMouse();
  2742.  
  2743.     if (!(wpeek = (WindowPeek)FrontWindow())) {
  2744.         SetRectRgn(gCursorRgn, -30000, -30000, 30000, 30000);
  2745.         WindowCursor(nil, nil, mouseLoc);
  2746.         return;
  2747.     }
  2748.  
  2749.     if (!IsAppWindow((WindowPtr)wpeek)) {
  2750.         SetRectRgn(gCursorRgn, -30000, -30000, 30000, 30000);
  2751.         SetCursor(gCursorPtr = &qd.arrow);
  2752.     }        /* Non-application windows get an arrow cursor. */
  2753.  
  2754.     if (gCursorPtr) {                            /* Do we already have a cursor... */
  2755.         if (PtInRgn(mouseLoc, gCursorRgn)) {    /* Are we still in the cursor area... */
  2756.             SetCursor(gCursorPtr);                /* Then set it to that. */
  2757.             return;
  2758.         }
  2759.     }
  2760.  
  2761.     SetRectRgn(gCursorRgn, -30000, -30000, 30000, 30000);
  2762.  
  2763.     for (wpeek = (WindowPeek)FrontWindow();; wpeek = wpeek->nextWindow) {
  2764.  
  2765.         if (!IsAppWindow((WindowPtr)wpeek)) break;
  2766.  
  2767.         if (!wpeek->visible) continue;        /* No cursors for invisible windows. */
  2768.  
  2769.         window = (WindowPtr)wpeek;
  2770.         srgn   = wpeek->strucRgn;
  2771.         frHndl = (FileRecHndl)GetWRefCon(window);
  2772.  
  2773.         proc = (frHndl) ? (*frHndl)->fileState.windowCursorProc : nil;
  2774.         if (!proc) {
  2775.             if (PtInRgn(mouseLoc, srgn)) {
  2776.                 SectRgn(gCursorRgn, srgn, gCursorRgn);
  2777.                 SetCursor(gCursorPtr = &qd.arrow);
  2778.                 return;
  2779.             }
  2780.         }
  2781.         else if ((*proc)(frHndl, window, mouseLoc)) return;
  2782.  
  2783.         DiffRgn(gCursorRgn, srgn, gCursorRgn);
  2784.     }
  2785.  
  2786.     SetCursor(gCursorPtr = &qd.arrow);
  2787. }
  2788.  
  2789.  
  2790.  
  2791. /*****************************************************************************/
  2792.  
  2793.  
  2794.  
  2795. WindowPtr    FrontWindowOfType(long wkind, Boolean firstVis)
  2796. {
  2797.     WindowPtr    window;
  2798.     FileRecHndl    frHndl;
  2799.     long        wk;
  2800.  
  2801.     wkind &= (kwIsPalette | kwIsModalDialog);
  2802.     for (window = nil; (window = GetNextWindow(window, 0)) != nil;) {
  2803.         if (firstVis)
  2804.             if (!(((WindowPeek)window)->visible))
  2805.                 continue;
  2806.         if (IsDAWindow(window))
  2807.             if (wkind == kwIsDocument)
  2808.                 return(window);
  2809.         if (((WindowPeek)window)->windowKind >= 1000) {
  2810.             frHndl = (FileRecHndl)GetWRefCon(window);
  2811.             if (frHndl) {
  2812.                 wk = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  2813.                 if (wk < wkind)  break;
  2814.                 if (wk == wkind) return(window);
  2815.             }
  2816.         }
  2817.     }
  2818.  
  2819.     return(nil);
  2820. }
  2821.  
  2822.  
  2823.  
  2824. /*****************************************************************************/
  2825.  
  2826.  
  2827.  
  2828. /* This function gets an alert, and handles hiliting of windows correctly.
  2829. ** The reason for this function is that there may be more than one hilited
  2830. ** window due to the possibility of floating palettes.  The calls to UnhiliteWindows
  2831. ** and HiliteWindows make sure that while the alert is up, there are no other
  2832. ** hilited windows. */
  2833.  
  2834. short    HCenteredAlert(short alertID, WindowPtr relatedWindow, ModalFilterUPP filter)
  2835. {
  2836.     short    itemHit;
  2837.  
  2838.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2839.  
  2840.     UnhiliteWindows();
  2841.     itemHit = CenteredAlert(alertID, relatedWindow, filter);
  2842.     HiliteWindows();
  2843.     return(itemHit);
  2844. }
  2845.  
  2846.  
  2847.  
  2848. /*****************************************************************************/
  2849. /*****************************************************************************/
  2850.  
  2851.  
  2852.  
  2853. /* This function gets the application window formats that were created with
  2854. ** the AppsToGo application editor.  The window formats are stored in the resource
  2855. ** 'WFMT' id #128.  They are first read in, and then they are unflattened
  2856. ** by calling HReadWindowFormats(). */
  2857.  
  2858. OSErr    GetWindowFormats(void)
  2859. {
  2860.     Handle    wfmt;
  2861.     OSErr    err;
  2862.  
  2863.     if (!(wfmt = GetAppResource('WFMT', 128, nil))) return(ResError());
  2864.     DetachResource(wfmt);
  2865.  
  2866.     err = HReadWindowFormats(wfmt);
  2867.     DisposeHandle(wfmt);
  2868.  
  2869.     return(err);
  2870. }
  2871.  
  2872.  
  2873.  
  2874. /*****************************************************************************/
  2875.  
  2876.  
  2877.  
  2878. /* This function is called to unflatten a window-format handle into separate
  2879. ** hierarchical document objects.  The assumption is that there is only one
  2880. ** of these multiple window definitions, and therefore if there is already
  2881. ** one in the global gWindowFormats, it is disposed of.  This is exactly the
  2882. ** behavior needed by the AppsToGo application editor. */
  2883.  
  2884. OSErr    HReadWindowFormats(Handle wfmt)
  2885. {
  2886.     TreeObjHndl        wobj;
  2887.     long            attr;
  2888.     short            i, j;
  2889.     OSErr            err;
  2890.     static OSType    *lastTypeListPtr;
  2891.  
  2892.     err = noErr;
  2893.     NewDocument(nil, 0, 0);        /* This resets the doc.increment value. */
  2894.  
  2895.     if (wfmt) {
  2896.         if (gWindowFormats)
  2897.             DisposeObjAndOffspring(gWindowFormats);
  2898.         if (!(gWindowFormats = NewRootObj(WFMTOBJ, 0))) return(memFullErr);
  2899.         err = HReadTree(gWindowFormats, wfmt);
  2900.     }
  2901.  
  2902.     if (!err) {
  2903.         gTypeListLen       = 0;
  2904.         gAppWindowAttr     = 0;
  2905.         gAppWindowType     = 0;
  2906.         gNoDefaultDocument = true;
  2907.         for (i = 0; i < (*gWindowFormats)->numChildren; ++i) {
  2908.             wobj = GetChildHndl(gWindowFormats, i);
  2909.             attr = mDerefWFMT(wobj)->attributes;
  2910.             if (!(attr & kwRuntimeOnlyDoc))
  2911.                 ++gTypeListLen;
  2912.             if (attr & kwDefaultDocType) {
  2913.                 gAppWindowAttr     = attr;
  2914.                 gAppWindowType     = mDerefWFMT(wobj)->sfType;
  2915.                 gNoDefaultDocument = false;
  2916.             }
  2917.         }
  2918.         if (gTypeListLen) {
  2919.             if (lastTypeListPtr)
  2920.                 DisposePtr((Ptr)lastTypeListPtr);
  2921.             gTypeListPtr = lastTypeListPtr = (OSType *)NewPtr(gTypeListLen * sizeof(OSType));
  2922.             if (!gTypeListPtr)
  2923.                 return(memFullErr);
  2924.             for (i = j = 0; i < (*gWindowFormats)->numChildren; ++i) {
  2925.                 wobj = GetChildHndl(gWindowFormats, i);
  2926.                 attr = mDerefWFMT(wobj)->attributes;
  2927.                 if (!(attr & kwRuntimeOnlyDoc))
  2928.                     gTypeListPtr[j++] = mDerefWFMT(wobj)->sfType;
  2929.             }
  2930.         }
  2931.     }
  2932.  
  2933.     return(err);
  2934. }
  2935.  
  2936.  
  2937.  
  2938. /*****************************************************************************/
  2939.  
  2940.  
  2941.  
  2942. /* This function is called to add a named 'WFMT' resource that isn't included in
  2943. ** the 'WFMT' id #128 standard resource.  The purpose for not including all of
  2944. ** the 'WFMT' resources into the id #128 is for speed reasons.  For really complex
  2945. ** applications, the number of items in the various windows and dialogs can cause
  2946. ** a huge number of handled to be created, thus slowing down the application.
  2947. ** By separating out one or more window definitions and saving them off, the size
  2948. ** of the main 'WFMT' resource can be reduced.  Named 'WFMT' resources should be
  2949. ** named with the document type used to reference them.  They are read in, used,
  2950. ** and then disposed of automatically. */
  2951.  
  2952. OSErr    GetSeparateWFMT(OSType sftype, short *numAdded)
  2953. {
  2954.     short            i, nadd, *naddptr;
  2955.     TreeObjHndl        wfmt;
  2956.     OSErr            err;
  2957.     Handle            hndl;
  2958.     Str15            str;
  2959.  
  2960.     nadd    = 0;
  2961.     naddptr = (numAdded) ? numAdded : &nadd;
  2962.  
  2963.     if (!sftype) {
  2964.         while (*naddptr)
  2965.             DisposeChild(NO_EDIT, gWindowFormats, --*naddptr);
  2966.         return(noErr);
  2967.     }
  2968.  
  2969.     *naddptr = 0;
  2970.     for (i = (*gWindowFormats)->numChildren; i;) {
  2971.         wfmt = GetChildHndl(gWindowFormats, --i);
  2972.         if (mDerefWFMT(wfmt)->sfType == sftype) return(noErr);
  2973.     }
  2974.  
  2975.     str[0] = 4;
  2976.     BlockMove(&sftype, str + 1, sizeof(OSType));
  2977.     hndl = GetNamedResource('WFMT', str);
  2978.     err = ResError();
  2979.     if (!err)
  2980.         if (!hndl)
  2981.             err = resNotFound;
  2982.     if (err) return(err);
  2983.  
  2984.     if (hndl) {
  2985.         DetachResource(hndl);
  2986.         wfmt = NewChild(NO_EDIT, gWindowFormats, *naddptr, WFMTOBJ, 0);
  2987.         if (!wfmt) {
  2988.             DisposeHandle(hndl);
  2989.             DisposeChild(NO_EDIT, gWindowFormats, *naddptr);
  2990.             return(memFullErr);
  2991.         }
  2992.  
  2993.         err = HReadTree(wfmt, hndl);        /* Unflatten the WFMT resource into the place-holder */
  2994.         DisposeHandle(hndl);
  2995.  
  2996.         if (err) {
  2997.             DisposeChild(NO_EDIT, gWindowFormats, *naddptr);
  2998.             return(err);
  2999.         }
  3000.  
  3001.         for (; (*wfmt)->numChildren;)
  3002.             MoveChild(NO_EDIT, wfmt, 0, gWindowFormats, (*naddptr)++);
  3003.  
  3004.         DisposeChild(NO_EDIT, gWindowFormats, *naddptr);
  3005.     }
  3006.  
  3007.     return(noErr);
  3008. }
  3009.  
  3010.  
  3011.  
  3012. /*****************************************************************************/
  3013. /*****************************************************************************/
  3014.  
  3015.  
  3016.  
  3017. /* This function adds a set of controls (and sets referenced by that set) to the
  3018. ** window.  The control sets are created with the AppsToGo application editor. */
  3019.  
  3020. OSErr    AddControlSet(WindowPtr window, OSType sftype, short visMode,
  3021.                       short xoffset, short yoffset, CObjCtlHndl retcoc)
  3022. {
  3023.     WindowPtr            oldPort;
  3024.     ControlHandle        ctl, dataCtl;
  3025.     CObjCtlHndl            coc;
  3026.     short                cocnum, i, j, len, ii, jj, vm, xo, yo, numAdded;
  3027.     OSType                sft;
  3028.     long                ofst, oldSize, newSize;
  3029.     TreeObjHndl            wfmt, cobj;
  3030.     char                str[256];
  3031.     OSErr                err;
  3032.     Rect                rct;
  3033.  
  3034.     if (!gWindowFormats) return(noErr);
  3035.  
  3036.     SetRect(&rct, 0, 0, 0, 0);
  3037.     dataCtl = NewControl(window, &rct, "\p", false, 0,0,0, gDataCtl + 7, sftype);
  3038.     if (!dataCtl) return(memFullErr);
  3039.  
  3040.     if (!(coc = (CObjCtlHndl)NewHandle(0x100))) return(memFullErr);
  3041.  
  3042.     err = GetSeparateWFMT(sftype, &numAdded);
  3043.     if (err) return(err);
  3044.  
  3045.     GetPort(&oldPort);
  3046.     SetPort(window);
  3047.  
  3048.     (*dataCtl)->contrlData = (Handle)coc;
  3049.     cocnum = 0;
  3050.  
  3051.     for (i = (*gWindowFormats)->numChildren; i;) {
  3052.         wfmt = GetChildHndl(gWindowFormats, --i);
  3053.         if (mDerefWFMT(wfmt)->sfType == sftype) {
  3054.             for (j = 0; j < (*wfmt)->numChildren; ++j) {
  3055.                 cobj = GetChildHndl(wfmt, j);
  3056.                 ctl  = MakeControl(window, cobj, visMode, xoffset, yoffset);
  3057.                 if (ctl) {
  3058.                     SetHandleSize((Handle)coc, (((++cocnum * sizeof(CObjCtl)) | 0xFF) + 1));
  3059.                     (**coc)[--cocnum].ctlObj  = cobj;    /* The handle was already big enough. */
  3060.                     (**coc)[cocnum  ].ctl     = ctl;
  3061.                     (**coc)[cocnum  ].visible = mDerefCtl(cobj)->visible;
  3062.                     (**coc)[cocnum++].procID  = mDerefCtl(cobj)->procID;
  3063.                     err = MemError();
  3064.                 }
  3065.                 if (!ctl) err = memFullErr;
  3066.                 if (err) {
  3067.                     SetHandleSize((Handle)coc, cocnum * sizeof(CObjCtl));
  3068.                     SetPort(oldPort);
  3069.                     GetSeparateWFMT(0, &numAdded);
  3070.                     return(err);
  3071.                 }
  3072.             }
  3073.  
  3074.             ofst = GetDataOffset(wfmt, offsetof(WFMTObj,title), kPStr, 1);
  3075.             GetPData(wfmt, ofst, (StringPtr)str);
  3076.             len = str[0];
  3077.             p2c((StringPtr)str);
  3078.             for (ii = 0; ii < len;) {
  3079.                 BlockMove(str + ii + 1, &sft, sizeof(OSType));
  3080.                 ii += sizeof(OSType) + 3;
  3081.                 vm = c2dec(str + ii, &jj);
  3082.                 ii += ++jj;
  3083.                 xo = c2dec(str + ii, &jj);
  3084.                 ii += ++jj;
  3085.                 yo = c2dec(str + ii, &jj);
  3086.                 ii += ++jj;
  3087.                 mDerefWFMT(wfmt)->sfType = 0;
  3088.                     /* Prevent self-references, which cause infinite recursion (boom). */
  3089.                 err = AddControlSet(window, sft, vm, xoffset + xo, yoffset + yo, retcoc);
  3090.                 mDerefWFMT(wfmt)->sfType = sftype;
  3091.                 if (err) {
  3092.                     SetHandleSize((Handle)coc, cocnum * sizeof(CObjCtl));
  3093.                     SetPort(oldPort);
  3094.                     GetSeparateWFMT(0, &numAdded);
  3095.                     return(err);
  3096.                 }
  3097.             }
  3098.         }
  3099.     }
  3100.  
  3101.     newSize = cocnum * sizeof(CObjCtl);
  3102.     SetHandleSize((Handle)coc, newSize);
  3103.  
  3104.     SetPort(oldPort);
  3105.  
  3106.     GetSeparateWFMT(0, &numAdded);
  3107.  
  3108.     if (retcoc) {
  3109.         oldSize = GetHandleSize((Handle)retcoc);
  3110.         SetHandleSize((Handle)retcoc, oldSize + newSize);
  3111.         err = MemError();
  3112.         if (err) return(err);
  3113.         BlockMove(*coc, (*(Handle)retcoc) + oldSize, newSize);
  3114.     }
  3115.  
  3116.     return(noErr);
  3117. }
  3118.  
  3119.  
  3120.  
  3121. /*****************************************************************************/
  3122.  
  3123.  
  3124.  
  3125. static pascal void    DefaultScrollAction(ControlHandle ctl, short part);
  3126. static pascal void    DefaultScrollAction(ControlHandle ctl, short part)
  3127. {
  3128.     short                delta, value;
  3129.     short                oldValue, min, max;
  3130.     ControlStyleInfo    cinfo;
  3131.     Boolean                vert;
  3132.     short                hArrowVal = 1;
  3133.     short                vArrowVal = 1;
  3134.     short                hPageVal = 10;
  3135.     short                vPageVal = 10;
  3136.  
  3137.     cinfo.scrollProc = nil;
  3138.     if (GetControlStyle(ctl, &cinfo)) {
  3139.         if (cinfo.hArrowVal) hArrowVal = cinfo.hArrowVal;
  3140.         if (cinfo.vArrowVal) vArrowVal = cinfo.vArrowVal;
  3141.         if (cinfo.hPageVal)  hPageVal  = cinfo.hPageVal;
  3142.         if (cinfo.vPageVal)  vPageVal  = cinfo.vPageVal;
  3143.     }
  3144.  
  3145.     vert = (((*ctl)->contrlRect.right - (*ctl)->contrlRect.left) == 16);
  3146.  
  3147.     if (part) {                        /* If it was actually in the control. */
  3148.  
  3149.         switch (part) {
  3150.             case inUpButton:
  3151.             case inDownButton:        /* One line. */
  3152.                 delta = (vert) ? vArrowVal : hArrowVal;
  3153.                 break;
  3154.             case inPageUp:            /* One page. */
  3155.             case inPageDown:
  3156.                 delta = (vert) ? vPageVal : hPageVal;
  3157.                 break;
  3158.         }
  3159.  
  3160.         if ( (part == inUpButton) || (part == inPageUp) )
  3161.             delta = -delta;        /* Reverse direction for an upper. */
  3162.  
  3163.         value = (oldValue = GetControlValue(ctl)) + delta;
  3164.         if (value < (min = GetControlMinimum(ctl))) value = min;
  3165.         if (value > (max = GetControlMaximum(ctl))) value = max;
  3166.  
  3167.         if (value != oldValue)
  3168.             SetControlValue(ctl, value);
  3169.  
  3170.         if (cinfo.scrollProc) (*cinfo.scrollProc)(ctl, part, oldValue, value);
  3171.     }
  3172. }
  3173.  
  3174. static Boolean    DefaultScroll(ControlHandle ctl, short part, EventRecord *event);
  3175. static Boolean    DefaultScroll(ControlHandle ctl, short part, EventRecord *event)
  3176. {
  3177.     short                oldValue, newValue;
  3178.     ControlStyleInfo    cinfo;
  3179.  
  3180.     static ControlActionUPP    cupp;
  3181.  
  3182.     oldValue = newValue = GetControlValue(ctl);
  3183.     switch (part) {
  3184.         case inThumb:
  3185.             if (TrackControl(ctl, event->where, nil)) {
  3186.                 newValue = GetControlValue(ctl);
  3187.                 if (oldValue != newValue) {
  3188.                     if (GetControlStyle(ctl, &cinfo))
  3189.                         if (cinfo.scrollProc)
  3190.                             (*cinfo.scrollProc)(ctl, part, oldValue, newValue);
  3191.                 }
  3192.             }
  3193.             break;
  3194.         default:
  3195.             if (!cupp) cupp = NewControlActionProc(DefaultScrollAction);
  3196.             TrackControl(ctl, event->where, cupp);
  3197.             newValue = GetControlValue(ctl);
  3198.             break;
  3199.     }
  3200.  
  3201.     return((oldValue != newValue) ? true : false);
  3202. }
  3203.  
  3204. static void    AddRect(Rect *r1, Rect *r2, Rect *r3);
  3205. static void    AddRect(Rect *r1, Rect *r2, Rect *r3)
  3206. {
  3207.     Rect    r;
  3208.  
  3209.     r = *r1;    
  3210.     r.top    += r2->top;
  3211.     r.left   += r2->left;
  3212.     r.bottom += r2->bottom;
  3213.     r.right  += r2->right;
  3214.     if ((r.left >= r.right) || (r.top >= r.bottom)) SetRect(&r, 0, 0, 0, 0);
  3215.     *r3 = r;
  3216. }
  3217.  
  3218. /* This function is used to create a control based on the control definition object.
  3219. ** The control definition objects are created with the AppsToGo application editor. */
  3220.  
  3221. ControlHandle    MakeControl(WindowPtr window, TreeObjHndl cobj, short visMode, short xoffset, short yoffset)
  3222. {
  3223.     WindowPtr            oldPort;
  3224.     ControlHandle        ctl;
  3225.     short                cctbID, tlen, slen, vis, maxTextLen;
  3226.     short                variant, rr, cc, ll, procID, mode;
  3227.     long                ofst;
  3228.     ControlStyleInfo    cinfo;
  3229.     CCTabHandle            cctbHndl;
  3230.     TEHandle            te;
  3231.     ListHandle            list;
  3232.     Handle                txt;
  3233.     StScrpHandle        styl;
  3234.     Ptr                    ptr;
  3235.     Point                cell;
  3236.     Rect                destRct, viewRct, brdrRct;
  3237.     char                hstate;
  3238.     CtlTemplate            **crsrc;
  3239.     short                txFont, txSize, fnum;
  3240.     Style                txFace;
  3241.  
  3242.     GetPort(&oldPort);
  3243.     SetPort(window);
  3244.  
  3245.     HLock((Handle)cobj);
  3246.     OffsetRect(&mDerefCtl(cobj)->rect, xoffset, yoffset);
  3247.  
  3248.     variant = (mDerefCtl(cobj)->procID & 0x0F);
  3249.     ctl = nil;
  3250.     vis  = mDerefCtl(cobj)->visible;
  3251.     vis |= visMode;
  3252.     vis ^= (visMode > 1);
  3253.     vis &= 0x01;
  3254.  
  3255.     cinfo.ctlID       = mDerefCtl(cobj)->ctlID;
  3256.     cinfo.trackProc   = nil;
  3257.     cinfo.scrollProc  = nil;
  3258.     cinfo.hArrowVal   = 0;
  3259.     cinfo.vArrowVal   = 0;
  3260.     cinfo.hPageVal    = 0;
  3261.     cinfo.vPageVal    = 0;
  3262.     cinfo.drawControl = nil;
  3263.     cinfo.fontSize    = mDerefCtl(cobj)->fontSize;
  3264.     cinfo.fontStyle   = mDerefCtl(cobj)->fontStyle;
  3265.     ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 1);
  3266.     GetPData(cobj, ofst, cinfo.keyEquivs);
  3267.     ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 2);
  3268.     GetPData(cobj, ofst, cinfo.font);
  3269.     ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 3);
  3270.     GetPData(cobj, ofst, cinfo.balloonHelp);
  3271.     txFont = window->txFont;
  3272.     txSize = window->txSize;
  3273.     txFace = window->txFace;
  3274.     procID = mDerefCtl(cobj)->procID;
  3275.     if (procID & 0x08) {
  3276.         TextFace(cinfo.fontStyle);
  3277.         fnum = 0;
  3278.         if (cinfo.font[0])
  3279.             GetFNum(cinfo.font, &fnum);
  3280.         TextFont(fnum);
  3281.         TextSize(cinfo.fontSize);
  3282.     }
  3283.  
  3284.     switch (procID & 0xFFF0) {
  3285.         case rTECtl:
  3286.             destRct = mDerefCtl(cobj)->extCtl.ctenew.destRct;
  3287.             viewRct = mDerefCtl(cobj)->extCtl.ctenew.viewRct;
  3288.             brdrRct = mDerefCtl(cobj)->extCtl.ctenew.brdrRct;
  3289.             maxTextLen = mDerefCtl(cobj)->extCtl.ctenew.maxTextLen;
  3290.             if (maxTextLen < 1) {
  3291.                 maxTextLen = -maxTextLen;
  3292.                 AddRect(&mDerefCtl(cobj)->rect, &destRct, &destRct);
  3293.                 AddRect(&mDerefCtl(cobj)->rect, &viewRct, &viewRct);
  3294.                 AddRect(&mDerefCtl(cobj)->rect, &brdrRct, &brdrRct);
  3295.             }
  3296.             else {
  3297.                 OffsetRect(&destRct, xoffset, yoffset);
  3298.                 OffsetRect(&viewRct, xoffset, yoffset);
  3299.                 OffsetRect(&brdrRct, xoffset, yoffset);
  3300.             }
  3301.             CTENew(gTECtl + variant,
  3302.                    false, window, &te,
  3303.                   &mDerefCtl(cobj)->rect,
  3304.                   &destRct, &viewRct, &brdrRct,
  3305.                    maxTextLen, mDerefCtl(cobj)->extCtl.ctenew.mode
  3306.             );
  3307.             if (te) {
  3308.                 UseControlStyle(ctl = CTEViewFromTE(te));
  3309.                 ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 4);
  3310.                 BlockMove((char *)GetDataPtr(cobj) + ofst, &tlen, sizeof(short));
  3311.                 txt = NewHandle(tlen);
  3312.                 if (txt) {
  3313.                     ptr = GetDataPtr(cobj);
  3314.                     BlockMove(ptr + ofst + sizeof(short), *txt, tlen);
  3315.                     slen = 0;
  3316.                     styl = nil;
  3317.                     if (mDerefCtl(cobj)->extCtl.ctenew.mode & cteStyledTE) {
  3318.                         ofst = GetDataOffset(cobj, ofst, kSDataBlock, 1);
  3319.                         BlockMove((char *)GetDataPtr(cobj) + ofst, &slen, sizeof(short));
  3320.                         if (slen)
  3321.                             styl = (StScrpHandle)NewHandle(slen);
  3322.                         if (styl) {
  3323.                             ptr = GetDataPtr(cobj);
  3324.                             BlockMove(ptr + ofst + sizeof(short), (Ptr)*styl, slen);
  3325.                         }
  3326.                     }
  3327.                     DisposeHandle(CTESwapText(te, txt, styl, false));
  3328.                     if (styl)
  3329.                         DisposeHandle((Handle)styl);
  3330.                     if (!(*ctl)->contrlHilite)
  3331.                          if (mDerefCtl(cobj)->extCtl.ctenew.mode & cteActive)
  3332.                             if (!CTEReadOnly(te))
  3333.                                 CTESetSelect(mDerefCtl(cobj)->min, mDerefCtl(cobj)->max, te);
  3334.                 }
  3335.                 UseControlStyle(nil);
  3336.             }
  3337.             break;
  3338.         case rListCtl:
  3339.             mode = mDerefCtl(cobj)->extCtl.clnew.mode;
  3340.             if (!gclvVariableSizeCells)
  3341.                 mode &= (0xFFFF - clVariable);
  3342.             list = CLNew(gListCtl + variant,
  3343.                          false,
  3344.                         &mDerefCtl(cobj)->rect,
  3345.                          mDerefCtl(cobj)->extCtl.clnew.numRows,
  3346.                          mDerefCtl(cobj)->extCtl.clnew.numCols,
  3347.                          mDerefCtl(cobj)->extCtl.clnew.cellHeight,
  3348.                          mDerefCtl(cobj)->extCtl.clnew.cellWidth,
  3349.                          mDerefCtl(cobj)->refCon,
  3350.                          window,
  3351.                          (mode & (0xFFFF - clVariable))
  3352.             );
  3353.             if (list) {
  3354.                 (*list)->listFlags |= 0x08;
  3355.                 ctl  = CLViewFromList(list);
  3356.                 ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 4);
  3357.                 BlockMove((char *)GetDataPtr(cobj) + ofst, &tlen, sizeof(short));
  3358.                 txt = NewHandle(tlen);
  3359.                 if (txt) {
  3360.                     ptr = GetDataPtr(cobj);
  3361.                     BlockMove(ptr + ofst + sizeof(short), *txt, tlen);
  3362.                     ofst = 0;
  3363.                     HLock(txt);
  3364.                     for (rr = 0; rr < mDerefCtl(cobj)->extCtl.clnew.numRows; ++rr) {
  3365.                         if (ofst >= tlen) break;
  3366.                         for (cc = 0; cc < mDerefCtl(cobj)->extCtl.clnew.numCols; ++cc) {
  3367.                             if (ofst >= tlen) break;
  3368.                             cell.h = cc;
  3369.                             cell.v = rr;
  3370.                             ll = ((unsigned char *)*txt)[ofst];
  3371.                             LSetCell(*txt + ofst + 1, ll, cell, list);
  3372.                             ofst += ++ll;
  3373.                         }
  3374.                     }
  3375.                     DisposeHandle(txt);
  3376.                 }
  3377.                 if (mode & clVariable)
  3378.                     (*gclvVariableSizeCells)(list);
  3379.                 else
  3380.                     if ((mDerefCtl(cobj)->extCtl.clnew.mode) & clDrawIt)
  3381.                         (*list)->listFlags &= (0xFFFF - 0x08);
  3382.             }
  3383.             break;
  3384.         case rCIconCtl:
  3385.             ctl = CCIconNew(window,
  3386.                            &mDerefCtl(cobj)->rect,
  3387.                  (StringPtr)mDerefCtl(cobj)->title,
  3388.                             false,
  3389.                             mDerefCtl(cobj)->value,
  3390.                             mDerefCtl(cobj)->min,
  3391.                             mDerefCtl(cobj)->max,
  3392.                             gCIconCtl + variant,
  3393.                             mDerefCtl(cobj)->refCon
  3394.             );
  3395.             break;
  3396.         case rPICTCtl:
  3397.             ctl = CPICTNew(window,
  3398.                           &mDerefCtl(cobj)->rect,
  3399.                 (StringPtr)mDerefCtl(cobj)->title,
  3400.                            false,
  3401.                            mDerefCtl(cobj)->value,
  3402.                            mDerefCtl(cobj)->min,
  3403.                            mDerefCtl(cobj)->max,
  3404.                            gPICTCtl + variant,
  3405.                            mDerefCtl(cobj)->refCon
  3406.             );
  3407.             break;
  3408.         default:
  3409.             procID = mDerefCtl(cobj)->procID;
  3410.             if (procID == -1) {
  3411.                 crsrc = (CtlTemplate **)GetResource('CNTL', mDerefCtl(cobj)->refCon);
  3412.                 if (crsrc) {
  3413.                     hstate = HGetState((Handle)crsrc);
  3414.                     HLock((Handle)crsrc);
  3415.                     ctl = NewControl(window,
  3416.                               &mDerefCtl(cobj)->rect,
  3417.                     (StringPtr)(*crsrc)->contrlTitle,
  3418.                                false,
  3419.                                (*crsrc)->contrlValue,
  3420.                                (*crsrc)->contrlMin,
  3421.                                (*crsrc)->contrlMax,
  3422.                                (*crsrc)->procID,
  3423.                                (*crsrc)->contrlRfCon
  3424.                     );
  3425.                     HSetState((Handle)crsrc, hstate);
  3426.                     if (((*crsrc)->procID & 0xFFF0) == popupMenuProc)
  3427.                         gPopupProc = (*ctl)->contrlDefProc;
  3428.                 }
  3429.                 if (ctl) break;
  3430.                 procID = 0;
  3431.             }
  3432.             if ((procID > rPICTCtl) && (procID < rDataCtl + 16))
  3433.                     procID += (gDataCtl - rDataCtl);
  3434.                         /* For AppsToGo to be able to use the target's CDEF's,
  3435.                         ** we have to have unique numbers for the extended controls.
  3436.                         ** AppsToGo has added a constant to all of the extended
  3437.                         ** controls for this reason.  We have to do the same for
  3438.                         ** these extra extended controls so that the contrlDefProc
  3439.                         ** is constant for compare purposes. */
  3440.             ctl = NewControl(window,
  3441.                       &mDerefCtl(cobj)->rect,
  3442.             (StringPtr)mDerefCtl(cobj)->title,
  3443.                        false,
  3444.                        mDerefCtl(cobj)->value,
  3445.                        mDerefCtl(cobj)->min,
  3446.                        mDerefCtl(cobj)->max,
  3447.                        procID,
  3448.                        mDerefCtl(cobj)->refCon
  3449.             );
  3450.             if (procID == scrollBarProc) cinfo.trackProc = DefaultScroll;
  3451.             break;
  3452.     }
  3453.  
  3454.     TextFont(txFont);
  3455.     TextSize(txSize);
  3456.     TextFace(txFace);
  3457.  
  3458.     OffsetRect(&mDerefCtl(cobj)->rect, -xoffset, -yoffset);
  3459.     HUnlock((Handle)cobj);
  3460.  
  3461.     if (ctl) {
  3462.         HiliteControl(ctl, mDerefCtl(cobj)->hilite);
  3463.         SetControlStyle(ctl, &cinfo);
  3464.         cctbID = mDerefCtl(cobj)->cctbID;
  3465.         if (cctbID) {
  3466.             if (gQDVersion > kQDOriginal) {
  3467.                 cctbHndl = (CCTabHandle)GetResource('cctb', cctbID);
  3468.                 if (cctbHndl)
  3469.                     SetControlColor(ctl, cctbHndl);
  3470.             }
  3471.         }
  3472.  
  3473.         if (vis) {
  3474.             switch (mDerefCtl(cobj)->procID & 0xFFF0) {
  3475.                 case rTECtl:
  3476.                     CTEShow((TEHandle)GetControlReference(ctl));
  3477.                     break;
  3478.                 case rListCtl:
  3479.                     CLShow((ListHandle)GetControlReference(ctl));
  3480.                     break;
  3481.                 default:
  3482.                     ShowControl(ctl);
  3483.                     break;
  3484.             }
  3485.         }
  3486.     }
  3487.  
  3488.     SetPort(oldPort);
  3489.     return(ctl);
  3490. }
  3491.  
  3492.  
  3493.  
  3494. /*****************************************************************************/
  3495.  
  3496.  
  3497.  
  3498. /* This function is called to return the handle of the Data control that has
  3499. ** a reference to all of the controls in the control set.  Once you get the
  3500. ** Data control, you can then look at the data in the control to get the handle
  3501. ** of the controls within the control set. */
  3502.  
  3503. CObjCtlHndl    GetControlSet(WindowPtr window, OSType sftype, ControlHandle *retDataCtl)
  3504. {
  3505.     ControlHandle    dataCtl;
  3506.     CObjCtlHndl        coc;
  3507.  
  3508.     for (dataCtl = nil; (dataCtl = CDataNext(window, dataCtl)) != nil;) {
  3509.         if ((*dataCtl)->contrlRfCon != sftype) continue;
  3510.         if (GetControlVariant(dataCtl) != 7)   continue;
  3511.         coc = (CObjCtlHndl)(*dataCtl)->contrlData;
  3512.         if (coc) {
  3513.             if (retDataCtl) *retDataCtl = dataCtl;
  3514.             return(coc);
  3515.         }
  3516.     }
  3517.  
  3518.     if (retDataCtl) *retDataCtl = nil;
  3519.     return(nil);
  3520. }
  3521.  
  3522.  
  3523.  
  3524. /*****************************************************************************/
  3525.  
  3526.  
  3527.  
  3528. /* This function is used to show or hide a set of controls. */
  3529.  
  3530. void    DisplayControlSet(WindowPtr window, OSType sftype, short visMode)
  3531. {
  3532.     WindowPtr        curPort;
  3533.     CObjCtlHndl        coc;
  3534.     short            i, vis;
  3535.     ControlHandle    ctl;
  3536.     Rect            rct;
  3537.  
  3538.     GetPort(&curPort);
  3539.     SetPort(window);
  3540.     coc = GetControlSet(window, sftype, nil);
  3541.     if (coc) {
  3542.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3543.             ctl = (**coc)[--i].ctl;
  3544.             vis = (**coc)[  i].visible;
  3545.             vis = ((vis | visMode) ^ (visMode > 1)) & 0x01;
  3546.             if (vis) {
  3547.                 switch ((**coc)[i].procID & 0xFFF0) {
  3548.                     case rTECtl:
  3549.                         CTEShow((TEHandle)GetControlReference(ctl));
  3550.                         break;
  3551.                     case rListCtl:
  3552.                         CLShow((ListHandle)GetControlReference(ctl));
  3553.                         break;
  3554.                     default:
  3555.                         ShowStyledControl(ctl);
  3556.                         break;
  3557.                 }
  3558.             }
  3559.             else {
  3560.                 switch ((**coc)[i].procID & 0xFFF0) {
  3561.                     case rTECtl:
  3562.                         rct = CTEHide((TEHandle)GetControlReference(ctl));
  3563.                         if (!(visMode & kwInvalOnHide)) ValidRect(&rct);
  3564.                         break;
  3565.                     case rListCtl:
  3566.                         rct = CLHide((ListHandle)GetControlReference(ctl));
  3567.                         if (!(visMode & kwInvalOnHide)) ValidRect(&rct);
  3568.                         break;
  3569.                     default:
  3570.                         HideStyledControl(ctl);
  3571.                         if (!(visMode & kwInvalOnHide)) {
  3572.                             rct = (*ctl)->contrlRect;
  3573.                             if (GetButtonVariant(ctl) == pushButProc)
  3574.                                 if ((*ctl)->contrlValue)
  3575.                                     InsetRect(&rct, kButtonFrameInset, kButtonFrameInset);
  3576.                             ValidRect(&rct);
  3577.                         }
  3578.                         break;
  3579.                 }
  3580.             }
  3581.         }
  3582.     }
  3583.     SetPort(curPort);
  3584. }
  3585.  
  3586.  
  3587.  
  3588. /*****************************************************************************/
  3589.  
  3590.  
  3591.  
  3592. /* This function is used to draw a set of controls. */
  3593.  
  3594. void    DrawControlSet(WindowPtr window, OSType sftype)
  3595. {
  3596.     CObjCtlHndl        coc;
  3597.     short            i, j;
  3598.     ControlHandle    ctl, cc;
  3599.     ListHandle        list;
  3600.  
  3601.     coc = GetControlSet(window, sftype, nil);
  3602.     if (coc) {
  3603.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3604.             ctl = (**coc)[--i].ctl;
  3605.             DoDraw1Control(ctl, false);
  3606.             switch ((**coc)[i].procID & 0xFFF0) {
  3607.                 case rTECtl:
  3608.                     for (j = 0; j < 2; ++j) {
  3609.                         cc = CTEScrollFromView(ctl, j);
  3610.                         if (cc) DoDraw1Control(cc, false);
  3611.                     }
  3612.                     break;
  3613.                 case rListCtl:
  3614.                     list = (ListHandle)GetControlReference(ctl);
  3615.                     if (list) {
  3616.                         if ((*list)->vScroll) DoDraw1Control((*list)->vScroll, false);
  3617.                         if ((*list)->hScroll) DoDraw1Control((*list)->hScroll, false);
  3618.                     }
  3619.                     break;
  3620.             }
  3621.         }
  3622.     }
  3623. }
  3624.  
  3625.  
  3626.  
  3627. /*****************************************************************************/
  3628.  
  3629.  
  3630.  
  3631. /* This function is used to dispose a set of controls. */
  3632.  
  3633. void    DisposeControlSet(WindowPtr window, OSType sftype)
  3634. {
  3635.     CObjCtlHndl        coc;
  3636.     ControlHandle    dataCtl;
  3637.     short            i;
  3638.  
  3639.     coc = GetControlSet(window, sftype, &dataCtl);
  3640.     if (coc) {
  3641.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3642.             HideStyledControl((**coc)[--i].ctl);
  3643.             DisposeControl((**coc)[i].ctl);
  3644.         }
  3645.         DisposeControl(dataCtl);
  3646.     }
  3647. }
  3648.  
  3649.  
  3650.  
  3651. /*****************************************************************************/
  3652.  
  3653.  
  3654.  
  3655. /* This function is used to dispose a set of controls. */
  3656.  
  3657. void    DisposeControlFromSet(ControlHandle ctl, OSType sftype)
  3658. {
  3659.     WindowPtr        window;
  3660.     CObjCtlHndl        coc;
  3661.     ControlHandle    dataCtl;
  3662.     short            i, s, o;
  3663.     Ptr                p;
  3664.  
  3665.     window = (*ctl)->contrlOwner;
  3666.     coc = GetControlSet(window, sftype, &dataCtl);
  3667.     if (coc) {
  3668.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3669.             if (ctl == (**coc)[--i].ctl) {
  3670.                 DisposeControl(ctl);
  3671.                 s = GetHandleSize((Handle)coc);
  3672.                 o = i * sizeof(CObjCtl);
  3673.                 p = (Ptr)*coc;
  3674.                 BlockMove(p + o + sizeof(CObjCtl), p + o, s - o - sizeof(CObjCtl));
  3675.                 SetHandleSize((Handle)coc, s - sizeof(CObjCtl));
  3676.                 if (s == sizeof(CObjCtl)) DisposeControl(dataCtl);
  3677.                 return;
  3678.             }
  3679.         }
  3680.     }
  3681. }
  3682.  
  3683.  
  3684.  
  3685. /*****************************************************************************/
  3686.  
  3687.  
  3688.  
  3689. /* This fuction is called to adjust all of the menus in the designated MBAR. 
  3690. ** The functions gets each menu handle, and then disables all of the menu items
  3691. ** for that menu.  It then calls the application to give the application the
  3692. ** chance to enable the appropriate menu items. */
  3693.  
  3694. Boolean    DoAdjustMBARMenus(WindowPtr window, short menuBarID)
  3695. {
  3696.     FileRecHndl                frHndl;
  3697.     short                    **mbar, i;
  3698.     long                    oldFlags;
  3699.     AdjustMenuItemsProcPtr    proc;
  3700.     Boolean                    redrawMenuBar;
  3701.     MenuHandle                menu;
  3702.  
  3703.     redrawMenuBar = false;
  3704.  
  3705.     proc = AdjustMenuItems;
  3706.     if (window) {
  3707.         if (((WindowPeek)window)->windowKind >= 1000) {
  3708.             frHndl = (FileRecHndl)GetWRefCon(window);
  3709.             if (frHndl)
  3710.                 proc = (*frHndl)->fileState.adjustMenuItemsProc;
  3711.         }
  3712.     }
  3713.  
  3714.     mbar = (short **)GetAppResource('MBAR', menuBarID, nil);
  3715.     if (mbar) {
  3716.         for (i = **mbar; i; --i) {
  3717.             menu = GetMenuHandle((*mbar)[i]);
  3718.             if (menu) {
  3719.                 oldFlags             = (*menu)->enableFlags;
  3720.                 (*menu)->enableFlags = oldFlags & 0x01;
  3721.                 redrawMenuBar       |= (*proc)(window, (*mbar)[i]);
  3722.                 if ((*menu)->enableFlags & 0xFFFFFFFEL) EnableItem(menu, 0);
  3723.                 else                                    DisableItem(menu, 0);
  3724.                 if ((oldFlags & 0x01) != ((*menu)->enableFlags & 0x01))
  3725.                     redrawMenuBar = true;
  3726.             }
  3727.         }
  3728.     }
  3729.  
  3730.     return(redrawMenuBar);
  3731. }
  3732.  
  3733.  
  3734.  
  3735. /*****************************************************************************/
  3736.  
  3737.  
  3738.  
  3739. /* This function is used to open all of the windows that are correctly designated
  3740. ** with the AppsToGo application editor.  You should call this in your application
  3741. ** at startup time if your application is editable with the AppsToGo application editor. */
  3742.  
  3743. OSErr    OpenRuntimeOnlyAutoNewWindows(void)
  3744. {
  3745.     FileRecHndl    frHndl;
  3746.     OSErr        err;
  3747.     short        i;
  3748.     TreeObjHndl    wobj;
  3749.     long        attr;
  3750.  
  3751.     err = noErr;
  3752.     if (gWindowFormats) {
  3753.         for (i = (*gWindowFormats)->numChildren; i;) {
  3754.             wobj = GetChildHndl(gWindowFormats, --i);
  3755.             attr = mDerefWFMT(wobj)->attributes;
  3756.             if (attr & kwRuntimeOnlyDoc) {
  3757.                 if (attr & kwAutoNew) {
  3758.                     err = NewDocumentWindow(&frHndl, mDerefWFMT(wobj)->sfType, true);
  3759.                     if (err) break;
  3760.                 }
  3761.             }
  3762.         }
  3763.     }
  3764.     return(err);
  3765. }
  3766.  
  3767.  
  3768.  
  3769. /*****************************************************************************/
  3770.  
  3771.  
  3772.  
  3773. /* This call can be done as two separate calls.  However, this function does both
  3774. ** functions of creating the document, and then giving the document a window.  It
  3775. ** also handles errors and puts up an error window if something goes wrong. */
  3776.  
  3777. OSErr    NewDocumentWindow(FileRecHndl *frHndl, OSType sftype, Boolean incTitleNum)
  3778. {
  3779.     FileRecHndl    ff, *ffp;
  3780.     OSErr        err;
  3781.     short        i, numAdded;
  3782.  
  3783.     gCursorPtr = nil;        /* Force recalc of cursor. */
  3784.  
  3785.     ffp = (frHndl) ? frHndl : &ff;
  3786.     *ffp = nil;
  3787.  
  3788.     if (!gWindowFormats) return(noErr);
  3789.  
  3790.     err = GetSeparateWFMT(sftype, &numAdded);
  3791.     if (!err) {
  3792.         for (i = (*gWindowFormats)->numChildren; i;) {
  3793.             if (sftype == mDerefWFMT(GetChildHndl(gWindowFormats, --i))->sfType) {
  3794.                 err = NewDocument(ffp, sftype, incTitleNum);
  3795.                 if (!err) {
  3796.                     err = DoNewWindow(*ffp, nil, FrontWindowOfType(kwIsDocument, true), (WindowPtr)-1);
  3797.                     if (err) DisposeDocument(*ffp);
  3798.                 }
  3799.                 break;
  3800.             }
  3801.         }
  3802.     }
  3803.     GetSeparateWFMT(0, &numAdded);
  3804.  
  3805.     return(err);
  3806. }
  3807.  
  3808.  
  3809.  
  3810. /*****************************************************************************/
  3811.  
  3812.  
  3813.  
  3814. /* This call can be done as two separate calls.  However, this function does both
  3815. ** functions of creating the document, and then giving the document a window.  It
  3816. ** also handles errors and puts up an error window if something goes wrong. */
  3817.  
  3818. OSErr    OpenDocumentWindow(FileRecHndl *frHndl, FSSpecPtr fileToOpen, char permission)
  3819. {
  3820.     FileRecHndl    ff, *ffp;
  3821.     WindowPtr    window, fwindow;
  3822.     OSErr        err;
  3823.     long        wkind;
  3824.  
  3825.     gCursorPtr = nil;        /* Force recalc of cursor. */
  3826.  
  3827.     ffp = (frHndl) ? frHndl : &ff;
  3828.     *ffp = nil;
  3829.  
  3830.     if (!gWindowFormats) return(noErr);
  3831.  
  3832.     err = OpenDocument(ffp, fileToOpen, permission);
  3833.     if (!err) {
  3834.         window = (**ffp)->fileState.window;
  3835.         if (!window) {
  3836.             err = DoNewWindow(*ffp, nil, FrontWindowOfType(kwIsDocument, true), (WindowPtr)-1);
  3837.             if (err) DisposeDocument(*ffp);
  3838.         }
  3839.         else {
  3840.             wkind   = (**ffp)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  3841.             fwindow = FrontWindowOfType(wkind, true);
  3842.             CleanSendInFront(window, fwindow);
  3843.         }
  3844.     }
  3845.  
  3846.     return(err);
  3847. }
  3848.  
  3849.  
  3850.  
  3851.